Search code examples
javascriptarray-merge

merge duplicate objects in an array and combine sub array of each object


I am trying to merge objects based off of Id, and merge each array that lives inside each account (object), but instead of merging the contents of accountList, the code overwrites the array, if there is a matching id.

I've made a new array and used the .find method to find matching objects based off there id, but stuck on how to merge the accountList together

const accounts = [
    {
    "Id": 103,
    "accountList": [
      {}
    ]
  },
  {
    "Id": 103,
    "accountList": [
      {
        "tokenId": "5aasdasdsdnjn3434nadd",
        "featureId": 2840
      }
    ]
  },
  {
    "Id": 112,
    "accountList": [
      {
        "tokenId": "5d30775bef4a722c38aefaaa",
        "featureId": 2877
      }
    ]
  },
    {
    "Id": 112,
    "accountList": [
      {
        "tokenId": "5d30775bef4a722c38aefccc",
        "featureId": 2856
      }
    ]
  }
]

let result = [];
accounts.forEach(account => {
  let match = result.find(r => r.Id === account.Id);
  // console.log(match)
  if(match) {
   Object.assign(match, account);
    //tried using spread operator instead of object assign, but didnt work
    //  match = {...match, ...account}
  } else {
    result.push(account);
  }
});

console.log( JSON.stringify(result, null, 2))

The result which i need is to merge the object based off their id, and merge the contents of the accountList together, like so:

[
  {
    "Id": 103,
    "accountList": [
      {
        "tokenId": "5aasdasdsdnjn3434nadd",
        "featureId": 2840
      }
    ]
  },
  {
    "Id": 112,
    "accountList": [
      {
        "tokenId": "5d30775bef4a722c38aefaaa",
        "featureId": 2877
      },
      {
        "tokenId": "5d30775bef4a722c38aefccc",
        "featureId": 2856
      }
    ]
  }
]

Solution

  • I think, reduce() would do the job:

    const accounts = [{"Id":103,"accountList":[{}]},{"Id":103,"accountList":[{"tokenId":"5aasdasdsdnjn3434nadd","featureId":2840}]},{"Id":112,"accountList":[{"tokenId":"5d30775bef4a722c38aefaaa","featureId":2877}]},{"Id":112,"accountList":[{"tokenId":"5d30775bef4a722c38aefccc","featureId":2856}]}];
    
    const result = [...accounts
            .reduce((r, o) => {
              const record = r.get(o.Id)||{}
              r.set(o.Id, {
                Id: o.Id,
                accountList: [
                  ...(record.accountList||[]),
                  ...o.accountList.filter(o => 
                    Object.keys(o).length != 0)
                ]            
              })
              return r
            }, new Map())
            .values()]
    
    console.log(result);
    .as-console-wrapper {min-height: 100%}