合并数组中的重复对象,并合并每个对象的子数组

时间:2019-08-30 11:09:12

标签: javascript array-merge

我试图基于Id合并对象,并合并每个account(对象)中的每个数组,但是如果有一个A,代码将覆盖该数组,而不是合并accountList的内容匹配的ID。

我制作了一个新数组,并使用.find方法基于id来找到匹配的对象,但仍坚持如何将accountList合并在一起

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))

我需要的结果是根据对象的ID合并对象,并将accountList的内容合并在一起,就像这样:

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

5 个答案:

答案 0 :(得分:1)

使用Array.prototype.reduce,我们可以将结果累积到最后的result数组中。

在reduce回调中,只需使用ID找到匹配的对象,然后合并accountList数组,而不是像在代码中那样合并该对象。

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);

答案 1 :(得分:1)

我认为35:04:28 可以完成这项工作:

reduce()
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 res = accounts.reduce((r,{Id,accountList}) => {
  const matchIdx = r.findIndex(item => item.Id == Id);
  return matchIdx < 0 ? 
    [...r,{Id, accountList: accountList.filter(obj => Object.values(obj).length != 0)}] :
    (r[matchIdx].accountList.push(...accountList), r);
}, []);

console.log(res);

答案 2 :(得分:0)

我认为您可以使用match.accountList.push(...account.accountList);代替对象分配,可以使用传播运算符将元素推入结果项(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);

答案 3 :(得分:0)

您可以尝试使用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 } ]

答案 4 :(得分: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());
}

这将合并所有具有相同ID的帐户。希望这会有所帮助:)