Группировка массива объектов

Рейтинг: -1Ответов: 3Опубликовано: 13.03.2023

Имеется массив объектов. Необходимо сгруппировать его по одному из ключей объекта.

const foods = [
  {id: 1, title: 'apple', type: 'fruit'},
  {id: 2, title: 'banana', type: 'fruit'},
  {id: 3, title: 'bird', type: 'meat'},
  {id: 4, title: 'beer', type: 'drinks'},
  {id: 5, title: 'cow', type: 'meat'},
]

Должен получиться следующий результат:

const foodTypes = [
  {
    type: 'fruit', 
    foods: [
      {id: 1, title: 'apple', type: 'fruit'},
      {id: 2, title: 'banana', type: 'fruit'},
    ]
  },
  {
    type: 'meat', 
    foods: [
      {id: 3, title: 'cow', type: 'meat'},
      {id: 4, title: 'bird', type: 'meat'},
    ]
  },
  {
    type: 'drinks', 
    foods: [
      {id: 5, title: 'beer', type: 'drinks'},
    ]
  },
]

Ответы

▲ 0Принят

В result положим все совпадения по type, далее создадим шаблон обьекта, который будем добавлять в foodTypes, и каждый найденный результат в result будем добавлять в object.foods , в конце функция добавит наш обьект в foodTypes.

 const foodTypes = [];
    
    function groupMassive(value) {
      const result = foods.filter((item) => {
        return item.type.includes(value);
      });
      const object = {
        type: "",
        foods: [],
      };
      object.type = result[0].type;
      result.forEach((item) => object.foods.push(item));
      foodTypes.push(object);
    }
    groupMassive("fruit");
    groupMassive("meat");
    groupMassive("drinks");

Если хотим автоматизировать, то создадим вторую функцию которая вернёт готовый массив

function returnMassive(massive) 
{
    const types = massive.filter(item => item.type)
    types.forEach(type => groupMassive(type)) 
}
returnMassive(foods)
▲ 2

Вот рабочий вариант через reduce

const foods = [
  {id: 1, title: 'apple', type: 'fruit'},
  {id: 2, title: 'banana', type: 'fruit'},
  {id: 3, title: 'bird', type: 'meat'},
  {id: 4, title: 'beer', type: 'drinks'},
  {id: 5, title: 'cow', type: 'meat'},
]

const grouper = key => array => 
  Object.values(array.reduce((acc,val) => {
    const property = val[key];
    acc[property] = acc[property] || {
      type: property,
      foods: []
    };
    acc[property].foods.push(val);
    return acc;
  },{}))

console.log(JSON.stringify((grouper('type')(foods)), null,2))

▲ 2

Более современный вариант с использованием Object.groupBy.

const foods = [
  {id: 1, title: 'apple', type: 'fruit'},
  {id: 2, title: 'banana', type: 'fruit'},
  {id: 3, title: 'bird', type: 'meat'},
  {id: 4, title: 'beer', type: 'drinks'},
  {id: 5, title: 'cow', type: 'meat'},
]

const res = Object.entries(
    Object.groupBy(foods, ({type}) => type))
          .map(([type, foods]) => ({type, foods}));

console.log(res);