I have some data in a non desirable format and I would like to flatten it.
Data:
[
{
team: "Team 1",
name: "John"
},
{
team: "Team 1",
name: "Stacy"
},
{
team: "Team 1",
name: "Jason"
},
{
team: "Team 2",
name: "Tim"
},
{
team: "Team 2",
name: "Andrew"
},
{
team: "Team 2",
name: "Steve"
}
,
{
team: "Team 3",
name: "Eric"
},
{
team: "Team 3",
name: "Frank"
},
{
team: "Team 3",
name: "Cory"
}
]
The desired result is:
[
{
team: "Team 1",
name: ["John", "Stacy", "Jason"],
count: 3
},
{
team: "Team 2",
name: ["Tim", "Andrew", "Steve"],
count: 3
},
{
team: "Team 3",
name: ["Eric", "Frank", "Cory"],
count: 3
}
]
I’ve tried looping through it and using Object.assing but that seemed the be the incorrect approach. Any suggestions on a good approach to flatted this data? Thanks
>Solution :
You can use Array.reduce.
In the reducer function, check whether the accumulator contains an item with the same team property. If so, increment its’s count property and push the current item’s name property to it’s name property.
const arr=[{team:"Team 1",name:"John"},{team:"Team 1",name:"Stacy"},{team:"Team 1",name:"Jason"},{team:"Team 2",name:"Tim"},{team:"Team 2",name:"Andrew"},{team:"Team 2",name:"Steve"},{team:"Team 3",name:"Eric"},{team:"Team 3",name:"Frank"},{team:"Team 3",name:"Cory"}];
const res = arr.reduce((a,b) => {
let itm = a.find(e => e.team == b.team);
if(itm){
itm.count++;
itm.name.push(b.name);
}else{
a.push({team: b.team, name: [b.name], count:1})
}
return a;
}, [])
console.log(res)
A more efficient solution:
const arr=[{team:"Team 1",name:"John"},{team:"Team 1",name:"Stacy"},{team:"Team 1",name:"Jason"},{team:"Team 2",name:"Tim"},{team:"Team 2",name:"Andrew"},{team:"Team 2",name:"Steve"},{team:"Team 3",name:"Eric"},{team:"Team 3",name:"Frank"},{team:"Team 3",name:"Cory"}];
const obj = arr.reduce((a,b) => {
let itm = a[b.team]
if(itm){
itm.count++;
itm.name.push(b.name);
}else{
a[b.team] = {team: b.team, name: [b.name], count: 0}
}
return a;
}, {})
const res = Object.keys(obj).map(e => obj[e])
console.log(res)