Search code examples
javascriptarraysobjectmerge

Merge array of objects with the same values by key


Please help. I am creating an API and this is the data structure that Iam trying to achive:

Groups:[{ groupId, name, members:[{userId, first_name, last_name, joinedDate, leftDate}] }] The members filed shoud contain all users that have the same groupId I need to group this input by groupId:

[ { groupId    : 1
  , name       : 'test group'
  , userId     : 2
  , first_name : 'Ross'
  , last_name  : 'Geller'
  , joinedDate : 2022-01-13T13: 25: 43.510Z
  , leftDate   : 2023-02-24T19: 07: 11.110Z
  } 
, { groupId    : 12
  , name       : 'test group 2'
  , userId     : 2
  , first_name : 'Ross'
  , last_name  : 'Geller'
  , joinedDate : 2022-01-13T00: 00: 00.000Z
  , leftDate   : null
  } 
, { groupId    : 12
  , name       : 'test group 2'
  , userId     : 6
  , first_name : 'Joey'
  , last_name  : 'Tribbiani'
  , joinedDate : 2022-01-13T00: 00: 00.000Z
  , leftDate   : null
  } 
] 

Into this output:

[ { groupId : 1
  , name    : 'test group'
  , members: 
    [ { userId     : 5
      , first_name : 'Monica'
      , last_name  : 'Gellar'
      , joinedDate : 2022-01-13T13: 25: 43.510Z
      , leftDate   : null
  } ] } 
, { groupId : 12
  , name    : 'test group 2'
  , members: 
    [ { userId     : 2
      , first_name : 'Ross'
      , last_name  : 'Geller'
      , joinedDate : 2022-01-13T00: 00: 00.000Z
      , leftDate   : null
      } 
    , { userId     : 6
      , first_name : 'Joey'
      , last_name  : 'Tribbiani'
      , joinedDate : 2022-01-13T00: 00: 00.000Z
      , leftDate   : null
} ] } ] 

Solution

  • You can use Array.prototype.reduce:

    const members = [
      {
        groupId: 1,
        name: 'test group',
        userId: 2,
        first_name: 'Ross',
        last_name: 'Geller',
        joinedDate: "2022-01-13T13:25:43.510Z",
        leftDate: "2023-02-24T19:07:11.110Z"   
      },
      {
        groupId: 12,
        name: 'test group 2',
        userId: 2,
        first_name: 'Ross',
        last_name: 'Geller',
        joinedDate: "2022-01-13T00:00:00.000Z",
        leftDate: null
      },
      {
        groupId: 12,
        name: 'test group 2',
        userId: 6,
        first_name: 'Joey',
        last_name: 'Tribbiani',
        joinedDate: "2022-01-13T00:00:00.000Z",
        leftDate: null
      }
    ];
    
    const grouped = members.reduce((acc, { groupId, name, ...member }) => {
      const existingGroup = acc.find(group => group.groupId === groupId);
      if (existingGroup)
        existingGroup.members.push(member);
      else
        acc.push({
          groupId,
          name,
          members: [
            member
          ]
        });
      return acc;
    }, []);
    
    console.log(grouped);