-2

There is an array of objects. I need to group it by one of the object keys.

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'},
]

should get the following result:

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'},
    ]
  },
]

I tried to solve through the reduce method, but something went wrong. Without using libraries.

const grouper = key => array => 
    array.reduce((acc, val) => {
        const property = val[key];
        acc[property] = acc[property] || [];
        acc[property].push(val);
        return acc;
    }, {})
Andrew
  • 1
  • 1
  • well that is going to not give you the result you want with the other objects.... It will give you the array for food. – epascarello Mar 13 '23 at 19:05
  • Does this answer your question? [javascript | Object grouping](https://stackoverflow.com/questions/21776389/javascript-object-grouping) – Konrad Mar 13 '23 at 19:06
  • Does this answer your question? [Most efficient method to groupby on an array of objects](https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects) – Wyck Mar 13 '23 at 20:13

4 Answers4

0

Reduce the array to a Map, and then you can convert the Map using Array.from() back to an array of objects:

const groupToMap = (pred, arr) => arr.reduce((acc, o) => {
  const key = pred(o)
  
  if(!acc.has(key)) acc.set(key, [])
  
  acc.get(key).push(o)
  
  return acc
}, new Map())

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 result = Array.from(
  groupToMap(o => o.type, foods),
  ([type, foods]) => ({ type, foods })
)

console.log(result)
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
0

Well if you want the format you are after, you need to use an object with the type string and foods array. Use Object.values to get the array of objects you are after.

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(grouper('type')(foods))
epascarello
  • 204,599
  • 20
  • 195
  • 236
0

My example is in two steps.

  1. Create a sorted object
  2. An array of objects is created

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' },
];

let obj = {};
foods.forEach(x => {
    obj[x.type] ? obj[x.type] = [...obj[x.type], x] : obj[x.type] = [x];
});

let fin = [];
for (const key in obj) {
    fin.push({
        type: key,
        foods: obj[key]
    });
};

console.log(fin);
54ka
  • 3,501
  • 2
  • 9
  • 24
0

You need toget values fromobject also is better to make without closure

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 = (array, key)=>{
  return Object.values(array.reduce((acc, current) => {
    const item = current[key];

    acc[item] = acc[item] || {
      foods: []
    };

    acc[item][key]=item;
    acc[item].foods.push(current);

    return acc;
  }, {}))
}

console.log(grouper(foods, 'type'));