-3

Basically I have this JavaScript array:

const a = [
  {name: 'Foo', place: 'US', age: 15},
  {name: 'Foo', place: 'UK', age: 21},
  {name: 'Bar', place: 'Canada', age: 20},
  {name: 'Bar', place: 'China', age: 22}
];

What is the fastest way to make it look like this? (Where the name becomes a single object property in the "a" array). How would I iterate over the array?

const a = [
  {
    name: 'Foo',
    data: [
      {
        place: 'US', age: 15
      },
      {
        place: 'UK', age: 21
      }
    ]
  },
  {
    name: 'Bar',
    data: [
      {
        place: 'Canada', age: 20
      },
      {
        place: 'China', age: 22
      }
    ]
  }
];

Thank you!

Robert Feduș
  • 311
  • 2
  • 16
  • That question is not a duplicate of your question. In your question, you want an array output, whereas the duplicated one produces an object. – Nick Parsons Sep 05 '20 at 15:44

2 Answers2

0

You can make use of reduce function to group data based on name property and then take Object.values.

var a = [
  {name: 'Foo', place: 'US', age: 15},
  {name: 'Foo', place: 'UK', age: 21},
  {name: 'Bar', place: 'Canada', age: 20},
  {name: 'Bar', place: 'China', age: 22}
];

var result = Object.values(a.reduce((acc, {name, ...rest})=>{
    acc[name] = acc[name] || {name, data:[]};
    acc[name].data = [...acc[name].data, rest];
    return acc;
},{}));

console.log(result);
gorak
  • 5,233
  • 1
  • 7
  • 19
0

One way could be to use an ES6 Map. You can use .reduce() to accumulate the objects in a to the Map. Each name can be a key in the map and each value within the map will be an array of objects which have that key as a name. Once you have built the Map, you can use Array.from() to convert the Map to an array, while also providing a mapping function to convert the entries [name, data[]] to objects while the Map to array conversion occurs.

See example below:

const a = [
  {name: 'Foo', place: 'US', age: 15},
  {name: 'Foo', place: 'UK', age: 21},
  {name: 'Bar', place: 'Canada', age: 20},
  {name: 'Bar', place: 'China', age: 22}
];

const res = Array.from(a.reduce((m, {name, ...r}) => {
  return m.set(name, (m.get(name) || []).concat(r));
}, new Map), ([name, data]) => ({name, data}));

console.log(res);
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64