-5

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

user3330820
  • 501
  • 2
  • 7
  • 17
  • 2
    What you are really wanting is a "groupBy". Do a search and will find many results for that operation – charlietfl Dec 19 '21 at 19:12
  • FYI, what you're asking for it NOT flattening. `Array.prototype.flat()` defines flattening an array and what you're asking for is not that. You're asking for grouping. – jfriend00 Dec 19 '21 at 19:20
  • 1
    @Dementic - The problem with your search is that the OP doesn't actually want flatten (they want grouping), so the problem for the OP is they don't know the right term to search for and don't realize that what they think it's called is wrong. This is the occasional bug-a-boo with search. If you don't know the right thing to search for, it may not help you. – jfriend00 Dec 19 '21 at 19:26
  • Thank you @jfriend00 I was not finding the proper results because I was thinking of flattening instead of grouping. – user3330820 Dec 19 '21 at 19:32
  • @jfriend00 agreed, on the other hand, i find it peculiar that we now need to also "Guess" or define the specs for a user that asks a question. Isnt that a bit far fetch for SO? – Rafael Herscovici Dec 20 '21 at 10:28
  • 1
    @Dementic - No guessing is involved if you look at the actual input/output data in the question, It's very clear there that this is not generic flattening and this is actually a good question in that regard (that they included a precise example of input/output). Unlike many question on stackoverflow, no guessing was required here. – jfriend00 Dec 20 '21 at 17:28

1 Answers1

-2

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)
Spectric
  • 30,714
  • 6
  • 20
  • 43