-2

I have this array of objects

[
  { id: '1', foo: 'bar' },
  { id: '1', foo: 'foo' },
  { id: '4', bar: 'foo' }
]

How could I merged it by id to get result below?

Desired result:

{
  '1': [
    { foo: 'bar' },
    { foo: 'foo' }
  ]
  '4': [
    { bar: 'foo' }
  ]
}

I tried Object.entries but this method won't work for what I'm doing.

Edit:

I read answers to this question and first of all none of them fully answers my question and second they are also no typescript answers.

All answers there was key => val while I need key => array of objects of that key

4b0
  • 21,981
  • 30
  • 95
  • 142
henroper
  • 127
  • 3
  • 9
  • 2
    You are not merging. You are grouping. Search for javascript group by id – mplungjan Jul 29 '21 at 12:15
  • 1
    ... how did the OP try? This is a classic [`reduce`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#syntax) task. – Peter Seliger Jul 29 '21 at 12:16
  • 1
    Duplicate of [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) I believe. – Behemoth Jul 29 '21 at 12:21
  • How is it then that the [first answer](https://stackoverflow.com/a/34890276/12834972) of that question provides a function that perfectly returns your desired result. Just use `groupBy(yourArray, 'id')` – Behemoth Jul 29 '21 at 14:12
  • 2
    Please don't vandalize your posts. By posting on the Stack Exchange network, you've granted a non-revocable right, under the [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) license, for Stack Exchange to distribute that content (i.e. regardless of your future choices). By Stack Exchange policy, the non-vandalized version of the post is the one which is distributed, and thus, any vandalism will be reverted. If you want to know more about deleting a post please see: [How does deleting work?](https://stackoverflow.com/help/what-to-do-instead-of-deleting-question) – 4b0 Jul 31 '21 at 04:38

2 Answers2

1

This is a classic reduce task ...

function groupItemRestById(collector, item) {
  const { id, ...rest } = item;
  const groupList = collector[id] || (collector[id] = []);

  groupList.push(rest);

  return collector;
}

console.log([

  { id: '1', foo: 'bar' },
  { id: '1', foo: 'foo' },
  { id: '4', bar: 'foo' },
  
].reduce(groupItemRestById, {}));
.as-console-wrapper { min-height: 100%!important; top: 0; }
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
  • @henroper ... I have no clue ... but after looking into the TS-Spec maybe something like ... `declare function groupItemRestById(collector: any, item: any): any;` ... might already do the trick. – Peter Seliger Jul 29 '21 at 13:36
0

You can simply use Array.reduce and group them accordingly.

const data = [
  { id: '1', foo: 'bar' },
  { id: '1', foo: 'foo' },
  { id: '4', bar: 'foo' }
]

const formatData = data => data.reduce((acc, {id, ...rest}) => {
  acc[id] ??= [];
  acc[id].push(rest);
  return acc;
}, {});

console.log(formatData(data));
.as-console-wrapper {
  max-height: 100% !important;
}
Nithish
  • 5,393
  • 2
  • 9
  • 24
  • Please check [this playground](https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgJIgA4FcwBE5hzIDeAUMhcsACYBcyAzmFKAOYA05lA2gNYQBPekxYhWAXWHM2pAL6lSoSLEQoAgggRYAtlgA2BAPZR8hElwp9BU0RPplKj5FaGNpYyW9sXks7uLkFBEMQJmRqAjh6dGw8SP9kAF5nLmIqOmQAcgBGTPZkGENDekyAIzgoTN9OCjSaEtz8wuKs5qrZGpJ0koAWPORyqBK231IA0mDQsALjbQJTImSACgjCaMwcBf8ASiSAPnDIgDooCGosJCWlxAR6DS1dAzBjBfziGnyjr9OmWV3Eg4OZA3bg0cTIAD8EOS-gA3FwQWCjtgGAALJY-MDbeEUU5gLBQEDAzTwjokP7wiYhBiGPQQI56QysJaFKBzOKEFaRbbYoA) once. – Nithish Jul 29 '21 at 15:27