Задать вопрос
@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 }
  • Вопрос задан
  • 207 просмотров
Подписаться 1 Простой 1 комментарий
Помогут разобраться в теме Все курсы
  • Яндекс Практикум
    Фронтенд-разработчик
    10 месяцев
    Далее
  • Skillfactory
    Профессия Веб-разработчик
    12 месяцев
    Далее
  • Яндекс Практикум
    Мидл фронтенд-разработчик
    5 месяцев
    Далее
Решения вопроса 3
0xD34F
@0xD34F Куратор тега JavaScript
Как можно получить кусок имени, по которому будем относить элемент массива к той или иной группе:

const getName = n => n.name.split(' ').pop();
// или
const getName = n => n.name.replace(/.+ /, '');
// или
const getName = n => n.name.match(/\S*$/)[0];
// или
const getName = n => n.name.slice(-~n.name.lastIndexOf(' '));

Дальше можно сделать просто:

const result = Object.values(arr.reduce((min, n) => {
  const name = getName(n);
  min[name] = +min[name]?.price < +n.price ? min[name] : n;
  return min;
}, {}));

Или сложно:

function group(data, key, val = n => n) {
  const getKey = key instanceof Function ? key : n => n[key];
  const getVal = val instanceof Function ? val : n => n[val];
  const result = new Map;

  for (const n of data) {
    const k = getKey(n);
    result.set(k, result.get(k) ?? []).get(k).push(getVal(n));
  }

  return result;
}

function max(data, key = n => n) {
  const getVal = key instanceof Function ? key : n => n[key];
  let result = null;

  for (const n of data) {
    const val = getVal(n);
    result = result?.[1] >= val ? result : [ n, val ];
  }

  return result?.[0];
}

const result = Array.from(
  group(arr, getName).values(),
  n => max(n, m => -m.price)
);
Ответ написан
@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 }
]
*/
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Можно сделать красиво:

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

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

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

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

Похожие вопросы