0

I generate the following json in my Node application:

    [ { id: 1,
        name: 'user1',
        sport: 'athletics',
        medal_count: '1' 
      },
      { id: 1,
        name: 'user1',
        sport: 'tennis',
        medal_count: '2' 
      },
      { id: 2,
        name: 'user2',
        sport: ['football'],
        medal_count: '2' 
      }
    ]

I'd now like to concatenate users so that they appear as a single object with the sport listed in an array and the medal_count aggegrated for the user. The above json would look like this:

    [ { id: 1,
        name: 'user1',
        sport: [
          'athletics',
          'tennis'
        ],
        medal_count: '3' 
      },
      { id: 2,
        name: 'user2',
        sport: 'football',
        medal_count: '2' 
      }
    ]

How is this done? Am I correct in thinking this should be done with a map reduce function?

2 Answers 2

2

Edited

let input = [{
  id: 1,
  name: 'user1',
  sport: 'athletics',
  medal_count: '1'
},
  {
    id: 1,
    name: 'user1',
    sport: 'tennis',
    medal_count: '2'
  },
  {
    id: 2,
    name: 'user2',
    sport: 'football',
    medal_count: '2'
  }
];

let grouped = {};
input.forEach(({id, name, sport, medal_count}) => {
  grouped[id] = grouped[id] || {id, name, sport: [], medal_count:0};
  if (!grouped[id].sport.includes(sport))
    grouped[id].sport.push(sport);
  grouped[id].medal_count = `${(+grouped[id].medal_count)+ (+medal_count)}`;
});
grouped = Object.values(grouped);

console.log(grouped);

Sign up to request clarification or add additional context in comments.

Comments

1

Yes, you are right:

'use strict';

const data = [{
  id: 1,
  name: 'user1',
  sport: 'athletics',
  medal_count: '1',
},
{
  id: 1,
  name: 'user1',
  sport: 'tennis',
  medal_count: '2',
},
{
  id: 2,
  name: 'user2',
  sport: 'football',
  medal_count: '2',
}];


const out = data.reduce((accumulator, item) => {
  if (accumulator[item.id]) {
    const group = accumulator[item.id];
    if (Array.isArray(group.sport)) {
      group.sport.push(item.sport);
    } else {
      group.sport = [group.sport, item.sport];
    }
    group.medal_count = `${(+group.medal_count) + (+item.medal_count)}`;
  } else {
    accumulator[item.id] = item;
  }
  return accumulator;
}, {});

console.log(JSON.stringify(out, null, 2));

Note that you are using numbers as strings for medal_count

4 Comments

Thanks. How do I ensure all sport objects are arrays and not just the ones with more than 1 sport?
I edited the code sample to ensure all sport objects are arrays, even if they only contain one value. Otherwise, thanks for the help.
Yeah, in that case, the if(Array.isArray is no more necessary
Ah yes. I see this works: ``` const out = data.reduce((accumulator, item) => { if (accumulator[item.id]) { const group = accumulator[item.id]; group.sport.push(item.sport); group.medal_count = ${(+group.medal_count) + (+item.medal_count)}; } else { accumulator[item.id] = item; item.sport = [item.sport] } return accumulator; }, {}); console.log(JSON.stringify(out, null, 2)); ```

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.