@hatealleverything

Как выбрать из массива элементы с минимальной ценой?

Есть массив объектов. Задача - выбрать наименьшие по цене среди подобных по полю name.

{ name: 'Corrupted Demon Eater', price: '3215.00', inStock: 1 },
{ name: 'Exalted Demon Eater', price: '1530.00', inStock: 1 },
{ name: 'Demon Eater', price: '2900.00', inStock: 1 },

{ name: 'Whalehook', price: '1000.00', inStock: 1 },
{ name: 'Whalehook', price: '590.00', inStock: 1 },
{ name: 'Whalehook', price: '259.20', inStock: 1 },
{ name: 'Whalehook', price: '259.15', inStock: 1 },
{ name: 'Autographed Whalehook', price: '243.00', inStock: 1 },
{ name: 'Autographed Whalehook', price: '344.00', inStock: 1 },
{ name: 'Autographed Whalehook', price: '199.00', inStock: 1 },
{ name: 'Inscribed Whalehook', price: '355.00', inStock: 1 },
{ name: 'Inscribed Whalehook', price: '655.00', inStock: 1 },
{ name: 'Inscribed Whalehook', price: '5555.00', inStock: 1 },

{ name: 'Inscribed Sylvan Cascade', price: '345.00', inStock: 1 },
{ name: 'Inscribed Sylvan Cascade', price: '96.18', inStock: 1 },
{ name: 'Inscribed Sylvan Cascade', price: '95.00', inStock: 1 },
{ name: 'Inscribed Sylvan Cascade', price: '266.71', inStock: 1 },
{ name: 'Inscribed Sylvan Cascade', price: '85.00', inStock: 1 }


Допустим у нас есть такие данных. Из этих данных мне нужно получить самые низкие по цене, но чтобы удалились другие из массива с подобным именем. Смог реализовать подобный метод, но только когда все названия одинаковые, но вот когда есть приставки по типу Inscribed и подобные, что-то у меня не сходится, может можно это как-то реализовать.
Возможно как-то получится через indexOf, как я предполагаю

{ name: 'Exalted Demon Eater', price: '1530.00', inStock: 1 },
{ name: 'Autographed Whalehook', price: '199.00', inStock: 1 },
{ name: 'Inscribed Sylvan Cascade', price: '85.00', inStock: 1 }
  • Вопрос задан
  • 173 просмотра
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
Object.values(arr.reduce((acc, n) => {
  const name = n.name.split(' ').pop();
  acc[name] = +acc[name]?.price < +n.price ? acc[name] : n;
  return acc;
}, {}))
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@galaxy
Задача определения подобных имен не очень понятна.
На приведенных данных, если бы существовала запись с name = "Demon Eater Whalehook", ее в какую группу относить?
Ответ написан
Seasle
@Seasle Куратор тега JavaScript
const prefixes = ['Inscribed', 'Autographed', 'Exalted', 'Corrupted'];
const prefixExpression = new RegExp(`^(${prefixes.join('|')})`, 'gi');

const items = [
  { name: 'Corrupted Demon Eater', price: '3215.00', inStock: 1 },
  { name: 'Exalted Demon Eater', price: '1530.00', inStock: 1 },
  { name: 'Demon Eater', price: '2900.00', inStock: 1 },

  { name: 'Whalehook', price: '1000.00', inStock: 1 },
  { name: 'Whalehook', price: '590.00', inStock: 1 },
  { name: 'Whalehook', price: '259.20', inStock: 1 },
  { name: 'Whalehook', price: '259.15', inStock: 1 },
  { name: 'Autographed Whalehook', price: '243.00', inStock: 1 },
  { name: 'Autographed Whalehook', price: '344.00', inStock: 1 },
  { name: 'Autographed Whalehook', price: '199.00', inStock: 1 },
  { name: 'Inscribed Whalehook', price: '355.00', inStock: 1 },
  { name: 'Inscribed Whalehook', price: '655.00', inStock: 1 },
  { name: 'Inscribed Whalehook', price: '5555.00', inStock: 1 },

  { name: 'Inscribed Sylvan Cascade', price: '345.00', inStock: 1 },
  { name: 'Inscribed Sylvan Cascade', price: '96.18', inStock: 1 },
  { name: 'Inscribed Sylvan Cascade', price: '95.00', inStock: 1 },
  { name: 'Inscribed Sylvan Cascade', price: '266.71', inStock: 1 },
  { name: 'Inscribed Sylvan Cascade', price: '85.00', inStock: 1 }
];

const getCheapest = items => {
  const store = items.reduce((accumulator, item) => {
    const type = item.name.replace(prefixExpression, '').trim();
    if (!accumulator.has(type)) {
      accumulator.set(type, []);
    }
    accumulator.get(type).push(item);
    
    return accumulator;
  }, new Map());
  const cheapest = store.values().reduce((accumulator, items) => {
    const minPrice = Math.min(...items.map(item => parseFloat(item.price)));
    const item = items.find(item => parseFloat(item.price) === minPrice);
    accumulator.push(item);
    
    return accumulator;
  }, []);
  
  return cheapest;
};

getCheapest(items);
/*
[
  { name: 'Exalted Demon Eater', price: '1530.00', inStock: 1 },
  { name: 'Autographed Whalehook', price: '199.00', inStock: 1 },
  { name: 'Inscribed Sylvan Cascade', price: '85.00', inStock: 1 }
]
*/
Ответ написан
Комментировать
Можно сделать красиво:

// Здесь структура сгруппированная по названию
const values = _.groupBy(data, 'name');

// Здесь структура сгруппированная по названию, и содержащая только самый дешевый вариант
const cheapItemsMap = _.mapValues(values, items => _.sortBy(items, 'price').reverse()[0]);

// Если нужен массив
const cheapItemsList = Object.values(cheapItemsMap );
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы