Сортировка массива объектов по цене (от наименьшей к наибольшей)

#javascript #reactjs #higher-order-functions

#javascript #reactjs #функции более высокого порядка

Вопрос:

Ниже приведены некоторые данные, с которыми я в настоящее время работаю при создании веб-приложения в React.js прямо сейчас я пытаюсь отсортировать массив объектов по цене от наименьшей к наибольшей, чтобы при нажатии кнопки массив сортировался и отображался в DOM от наименьшей к наибольшей.

Пара вещей, которые я должен учитывать, заключается в том, что все цены представлены в виде строк с символом ‘$’ в качестве первого символа (НАПРИМЕР, ’18 долларов’), а второй объект в цене массива — «Предлагаемое пожертвование».

 studios: [
  {
    name: "Whole Yoga",
    price: "$17.00"
  },
  {
    name: "Rino Yoga Social",
    price: "Suggested Donation"
  },
  {
    name: "Samadhi Yoga",
    price: "$20.00"
  },
  {
    name: "Corepower Yoga",
    price: "$25.00"
  },
  {
    name: "The River Yoga",
    price: "$20.00"
  },
  {
    name: "Endorphin Yoga",
    price: "$10.00"
  },
  {
    name: "Kindness Yoga",
    price: "$20.00"
  },
  {
    name: "Yoga High",
    price: "$15.00"
  },
  {
    name: "Freyja Project",
    price: "$22.00"
  },
  {
    name: "Kula Yoga",
    price: "$17.00"
  }
 ]
  

До сих пор я использовал цикл while, чтобы удалить символ ‘$’ в начале строки, затем использовал метод .replace(), чтобы заменить «Предлагаемое пожертвование» на ‘00.00’ и проанализировать все цены.

Проблема, с которой я сталкиваюсь сейчас, заключается в том, что новый массив отсортированных цен не имеет ничего общего с исходными данными (их ничто не связывает), поэтому я просто возвращаю массив отсортированных цен, с которым я ничего не могу сделать. У кого-нибудь есть идеи о том, как мне следует поступить по этому поводу?

 priceFilter = () => {
    let newArr = []

    return this.props.studios.filter( studio => { 
      let price = studio.price;
      while(price.charAt(0) === '$') {
       price = price.substr(1);
      }
      price = price.replace('Suggested Donation', '00.00')
      let parsedPrice = parseInt(price);
      newArr.push(parsedPrice)
      return newArr.sort((a,b) => (a - b));
    })
  }
  

Ответ №1:

Преобразуйте ваши значения в числа. Исходя из вашего кода, ваша предлагаемая цена должна быть равна 0, поэтому мы используем это, если цена не начинается со знака доллара '$'

 const studios = [
  {
    name: "Whole Yoga",
    price: "$17.00"
  },
  {
    name: "Rino Yoga Social",
    price: "Suggested Donation"
  },
  {
    name: "Samadhi Yoga",
    price: "$20.00"
  },
  {
    name: "Corepower Yoga",
    price: "$25.00"
  },
  {
    name: "The River Yoga",
    price: "$20.00"
  },
  {
    name: "Endorphin Yoga",
    price: "$10.00"
  },
  {
    name: "Kindness Yoga",
    price: "$20.00"
  },
  {
    name: "Yoga High",
    price: "$15.00"
  },
  {
    name: "Freyja Project",
    price: "$22.00"
  },
  {
    name: "Kula Yoga",
    price: "$17.00"
  }
 ]

priceFilter = (vals) => {
  return vals.sort((a,b) => {
    const aPrice = a.price[0] === '$' ? parseFloat(a.price.slice(1,-1)) : 0;
    const bPrice = b.price[0] === '$' ? parseFloat(b.price.slice(1,-1)) : 0;
    return aPrice - bPrice;
  });
}

console.log(priceFilter(studios));  

Ответ №2:

Вы можете написать пользовательскую сортировку с помощью Array.prototype.sort (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort ).

 const compare = (a, b) => {
  const aPrice = Number(a.price.replace(/[^0-9.-] /g,""));
  const bPrice = Number(b.price.replace(/[^0-9.-] /g,""));

  return aPrice - bPrice
};


const sortedStudios = this.props.studios.sort(compare);
  

Ответ №3:

Вы могли бы использовать функцию для получения значения для сортировки, а затем использовать дельту в качестве повторного результата для метода сортировки.

 const getValue = ({ price }) =>  price.slice(1) || 0;

var studios = [{ name: "Whole Yoga", price: "$17.00" }, { name: "Rino Yoga Social", price: "Suggested Donation" }, { name: "Samadhi Yoga", price: "$20.00" }, { name: "Corepower Yoga", price: "$25.00" }, { name: "The River Yoga", price: "$20.00" }, { name: "Endorphin Yoga", price: "$10.00" }, { name: "Kindness Yoga", price: "$20.00" }, { name: "Yoga High", price: "$15.00" }, { name: "Freyja Project", price: "$22.00" }, { name: "Kula Yoga", price: "$17.00" }];

studios.sort((a, b) => getValue(a) - getValue(b));

console.log(studios);  
 .as-console-wrapper { max-height: 100% !important; top: 0; }  

Комментарии:

1. Не похоже, что это относится к случаю, когда цена является «Предлагаемым пожертвованием»

2. @weilandia, извините, что не увидел этого. пожалуйста, смотрите редактирование.

Ответ №4:

Вот так. 🙂

 let studios = [{
    name: "Whole Yoga",
    price: "$17.00"
  },
  {
    name: "Rino Yoga Social",
    price: "Suggested Donation"
  },
  {
    name: "Samadhi Yoga",
    price: "$20.00"
  },
  {
    name: "Corepower Yoga",
    price: "$25.00"
  },
  {
    name: "The River Yoga",
    price: "$20.00"
  },
  {
    name: "Endorphin Yoga",
    price: "$10.00"
  },
  {
    name: "Kindness Yoga",
    price: "$20.00"
  },
  {
    name: "Yoga High",
    price: "$15.00"
  },
  {
    name: "Freyja Project",
    price: "$22.00"
  },
  {
    name: "Kula Yoga",
    price: "$17.00"
  }
];
console.log("Unsorted", studios);

studios.sort(({
  price: a
}, {
  price: b
}) => {
  //parseFloat will be Nan if it cannot parse the string into a number
  //the only problem here is that any non int string will turn into 0
  a = parseFloat(a.slice(1), 10) || 0;
  b = parseFloat(b.slice(1), 10) || 0;

  return a - b;
});

console.log("Sorted", studios);  

Комментарии:

1. Обратите внимание, что parseInt игнорирует десятичные дроби

Ответ №5:

Вероятно, вы хотите сортировать объекты по цене вместо сортировки цен:

 const studios = [{"name":"Whole Yoga","price":"$17.00"},{"name":"Rino Yoga Social","price":"Suggested Donation"},{"name":"Samadhi Yoga","price":"$20.00"},{"name":"Corepower Yoga","price":"$25.00"},{"name":"The River Yoga","price":"$20.00"},{"name":"Endorphin Yoga","price":"$10.00"},{"name":"Kindness Yoga","price":"$20.00"},{"name":"Yoga High","price":"$15.00"},{"name":"Freyja Project","price":"$22.00"},{"name":"Kula Yoga","price":"$17.00"}];

const parsePrice = x => parseFloat(x.replace(/^$/, '')) || 0
const sortedStudios = studios
  .slice()
  .sort((a, b) => parsePrice(a.price) - parsePrice(b.price))

console.log(sortedStudios)  

Ответ №6:

Спасибо всем за помощь! Это решение сработало для меня.

 priceFilter = () => {
    let ordered = studios.sort((a, b) => (a.price > b.price) ? 1 : -1);
    let lastElement = ordered.pop();
    return ordered.unshift(lastElement);
  }