JavaScript通过id合并对象

Tam*_*am2 36 javascript arrays underscore.js

在Javascript中合并两个数组的正确方法是什么?

我有两个数组(例如):

var a1 = [{ id : 1, name : "test"}, { id : 2, name : "test2"}]
var a2 = [{ id : 1, count : "1"}, {id : 2, count : "2"}]
Run Code Online (Sandbox Code Playgroud)

我希望能够得到类似的东西:

var a3 = [{ id : 1, name : "test", count : "1"}, 
          { id : 2, name : "test2", count : "2"}]
Run Code Online (Sandbox Code Playgroud)

基于'id'字段连接两个数组的位置,简单地添加额外数据.

我尝试使用_.union它,但它只是将第二个数组中的值覆盖到第一个数组中

Gru*_*nny 37

这应该做的伎俩:

var mergedList = _.map(a1, function(item){
    return _.extend(item, _.findWhere(a2, { id: item.id }));
});
Run Code Online (Sandbox Code Playgroud)

这假设a1中第二个对象的id应该是2而不是"2"

  • 如果a2在数组中的项数多于a1,则无效. (6认同)
  • 请查看http://stackoverflow.com/a/39127782/146384(仅使用`_.unionBy`) (4认同)
  • [Lodash](https://github.com/lodash/lodash/wiki/Changelog#v400)使用iteratee弃用了`_.findWhere`以支持`_.find`,所以请使用`_.find(a2,{ id:item.id})`而不是. (2认同)

And*_*nis 34

简短的 ES6 解决方案

const a3 = a1.map(t1 => ({...t1, ...a2.find(t2 => t2.id === t1.id)}))
Run Code Online (Sandbox Code Playgroud)

  • 它不会合并仅在 a2 中找到的 id (5认同)
  • @Gabriel我认为要求是有两个共享 id 但具有不同属性的列表。 (2认同)

Ori*_*iol 14

假设ID是字符串并且顺序无关紧要,您可以

  1. 创建哈希表.
  2. 迭代两个数组并将数据存储在哈希表中,由ID索引.如果已存在具有该ID的某些数据,请使用Object.assign(ES6,可以进行多层填充)进行更新.
  3. 获取包含哈希映射值的数组.
var hash = Object.create(null);
a1.concat(a2).forEach(function(obj) {
    hash[obj.id] = Object.assign(hash[obj.id] || {}, obj);
});
var a3 = Object.keys(hash).map(function(key) {
    return hash[key];
});
Run Code Online (Sandbox Code Playgroud)

在ECMAScript6中,如果ID不一定是字符串,您可以使用Map:

var hash = new Map();
a1.concat(a2).forEach(function(obj) {
    hash.set(obj.id, Object.assign(hash.get(obj.id) || {}, obj))
});
var a3 = Array.from(hash.values());
Run Code Online (Sandbox Code Playgroud)


Alb*_*rto 10

ES6简化了这一点:

let merge = (obj1, obj2) => ({...obj1, ...obj2});
Run Code Online (Sandbox Code Playgroud)

请注意,重复的键将被合并,并且第二个对象的值将占上风,而第一个对象的重复值将被忽略

例:

let obj1 = {id: 1, uniqueObj1Key: "uniqueKeyValueObj1", repeatedKey: "obj1Val"};
let obj2 = {id: 1, uniqueObj2Key: "uniqueKeyValueObj2", repeatedKey: "obj2Val"};

merge(obj1, obj2)
// {id: 1, uniqueObj1Key: "uniqueKeyValueObj1", repeatedKey: "obj2Val", uniqueObj2Key: "uniqueKeyValueObj2"}
merge(obj2, obj1)
// {id: 1, uniqueObj2Key: "uniqueKeyValueObj2", repeatedKey: "obj1Val", uniqueObj1Key: "uniqueKeyValueObj1"}
Run Code Online (Sandbox Code Playgroud)

  • 这不是问题的答案。请检查预期结果并改进您的答案,或将其删除。 (2认同)
  • 如果列表的顺序不同,我认为这不起作用。 (2认同)

Dai*_*ima 9

减少版本.

var a3 = a1.concat(a2).reduce((acc, x) => {
    acc[x.id] = Object.assign(acc[x.id] || {}, x);
    return acc;
}, {});
_.values(a3);
Run Code Online (Sandbox Code Playgroud)

我认为这是功能语言的常见做法.

  • 如果你想跳过使用 lodash,简单的方法是 `Object.values` 或 `Object.keys(a3).map(k => a3[k])` (2认同)

bor*_*a89 5

Lodash 实现:

var merged = _.map(a1, function(item) {
    return _.assign(item, _.find(a2, ['id', item.id]));
});
Run Code Online (Sandbox Code Playgroud)

结果:

[  
   {  
      "id":1,
      "name":"test",
      "count":"1"
   },
   {  
      "id":2,
      "name":"test2",
      "count":"2"
   }
]
Run Code Online (Sandbox Code Playgroud)

  • 如果 a2 的数组项数多于 a1,则此方法不起作用 (3认同)

Nic*_*ick 5

已经有很多很好的答案,我将添加另一个来自我昨天需要解决的实际问题的答案。

我有一组带有用户 ID 的消息,以及一组包含用户名和其他详细信息的用户。这就是我设法将用户详细信息添加到消息中的方法。

var messages = [{userId: 2, content: "Salam"}, {userId: 5, content: "Hello"},{userId: 4, content: "Moi"}];
var users = [{id: 2, name: "Grace"}, {id: 4, name: "Janetta"},{id: 5, name: "Sara"}];

var messagesWithUserNames = messages.map((msg)=> {
  var haveEqualId = (user) => user.id === msg.userId
  var userWithEqualId= users.find(haveEqualId)
  return Object.assign({}, msg, userWithEqualId)
})
console.log(messagesWithUserNames)
Run Code Online (Sandbox Code Playgroud)


小智 5

普通 JS 解决方案

const a1 = [{ id : 1, name : "test"}, { id : 2, name : "test2"}]
const a2 = [{ id : 1, count : "1"}, {id : 2, count : "2"}]

const merge = (arr1, arr2) => {
  const temp = []

  arr1.forEach(x => {
    arr2.forEach(y => {
      if (x.id === y.id) {
        temp.push({ ...x, ...y })
      }
    })
  })

  return temp
}

console.log(merge(a1, a2))
Run Code Online (Sandbox Code Playgroud)