4

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
      }
    ]
  }
]
5
  • ahh sorry i clicked the wrong one Commented Sep 4, 2019 at 10:19
  • No worries, I was glad to help. Commented Sep 4, 2019 at 10:24
  • I updated my code, initially the empty object was also included. This has been fixed now. My bad. Commented Sep 4, 2019 at 10:55
  • Thank you to everyone who helped :) Commented Sep 4, 2019 at 13:09
  • Does this answer your question? Merge duplicate objects in array of objects Commented May 9, 2022 at 20:30

5 Answers 5

2

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%}

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

2 Comments

but if accountlist:{} it also pushed
@RakibulIslam : That doesn't seem to be the case according to OP's example.
1

You can try to use Array.concat:

    let result = [];
    accounts.forEach(account => {
      let match = result.find(r => r.Id === account.Id);
      // console.log(match)
      if(match) {
        match.accountList = match.accountList.concat(account.accountList);
      } else {
        result.push(account);
      }
    });

for (let res of result) {
  console.log('res.Id: ', res.Id, res.accountList)
}

// res.Id:  103 [ {}, { tokenId: '5aasdasdsdnjn3434nadd', featureId: 2840 } ]
// res.Id:  112 [ { tokenId: '5d30775bef4a722c38aefaaa', featureId: 2877 },
//   { tokenId: '5d30775bef4a722c38aefccc', featureId: 2856 } ]

Comments

1

Using Array.prototype.reduce we can accumulate the results in the final result array.

In the reduce call back just find the matching object using Id and merge the accountList array and not the object as you were doing in your code.

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((acc, account) => {
     let match = acc.find(r => r.Id === account.Id);
     if(match) {
       match.accountList.push(...account.accountList); //push previous array
     } else {
       const act = { ...account }; 
       act.accountList = account.accountList.filter((obj) => Object.keys(obj).length);
       acc.push(act);
     }
     return acc;
}, []);
console.log(result);

Comments

0

I think you could use match.accountList.push(...account.accountList); instead of the object assign, spread operator can be used to push the element into the result item(match):

let 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 => {
  (match = result.find(r => r.Id === account.Id), match ? match.accountList.push(...account.accountList) : result.push(account))
});
console.log(result);

Comments

0
const isNotEmptyObject = objc => Object.entries(objc).length > 0;

function mergeAccounts(accounts) {
    const uniqueAccounts = new Map();
    accounts.forEach(account => {
        if(uniqueAccounts.has(account.Id)) {
            let uniqueAccount = uniqueAccounts.get(account.Id);
            if(account.accountList && account.accountList.length > 0)
                uniqueAccount.accountList.push(...account.accountList);
                uniqueAccount.accountList = uniqueAccount.accountList.filter(isNotEmptyObject);
        } else {
            uniqueAccounts.set(account.Id, account);
        }
    });
  return Array.from(uniqueAccounts.values());
}

This will merge all the accounts having same ids. Hope this helps :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.