合并两个具有相同键的对象数组,某些对象的值可能不相同?

3

我想合并两个对象数组。键名相同但是值可能不同。

任何解决方案都可以,最好使用javascript编写,但是python也可以。

以下是示例数据:

var g= [ 
    { id: 36, name: 'AAA', goal: 'yes' , 'random':27},
    { id: 40, name: 'BBB', goal: 'yes' },
    { id: 39, name: 'JJJ', goal: 'yes' },
    { id: 27, name: 'CCC', goal: 'yes' , lag: "23.3343"}];


var c= [ 
    { id: 36, name: 'AAA', goal: 'yes', color:"purple" },
    { id: 40, name: 'BBB', circle: 'yes', color:"purple" },
    { id: 100, name: 'JJJ', circle: 'yes'} ];

我的期望输出应该是:

 var finalData = [{
 { id: 36, name: 'AAA', goal: 'yes' ,'random':27, color:"purple"},
 { id: 40, name: 'BBB', circle: 'yes', color:"purple"},
 { id: 39, name: 'JJJ', goal: 'yes' },
 { id: 27, name: 'CCC', goal: 'yes' ,lag: "23.3343"},
 { id: 100, name: 'JJJ', circle: 'yes' }

  }]

这是我的当前代码,它在某种程度上有效,但它不会添加可能遗漏的键。

var finalData = [];
for(var i in g){
   var shared = false;
   for (var j in c)
       if (c[j].name == g[i].name) {
           shared = true;
           break;
       }
   if(!shared) finalData.push(g[i])
}
finalData = finalData.concat(c); 

finalData

有哪些项目具有相同的键名 goal - Nishant
可能是合并两个对象数组的重复问题。 - Nishant
3个回答

4
你可以使用 Map 来保证相同的 id 在同一个对象中,而使用 Object.assign 来创建独立的对象。

var g = [{ id: 36, name: 'AAA', goal: 'yes', 'random': 27 }, { id: 40, name: 'BBB', goal: 'yes' }, { id: 39, name: 'JJJ', goal: 'yes' }, { id: 27, name: 'CCC', goal: 'yes', lag: "23.3343" }],
    c = [{ id: 36, name: 'AAA', goal: 'yes', color: "purple" }, { id: 40, name: 'BBB', circle: 'yes', color: "purple" }, { id: 100, name: 'JJJ', circle: 'yes' }],
    map = new Map,
    result = g.concat(c).reduce(function (r, o) {
        var temp;
        if (map.has(o.id)) {
            Object.assign(map.get(o.id), o);
        } else {
            temp = Object.assign({}, o);
            map.set(temp.id, temp);
            r.push(temp);
        }
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

不需要使用reduce和concat的版本。

function merge(o) {
    var temp;
    if (map.has(o.id)) {
        Object.assign(map.get(o.id), o);
        return;
    }
    temp = Object.assign({}, o);
    map.set(temp.id, temp);
    result.push(temp);
}

var g = [{ id: 36, name: 'AAA', goal: 'yes', 'random': 27 }, { id: 40, name: 'BBB', goal: 'yes' }, { id: 39, name: 'JJJ', goal: 'yes' }, { id: 27, name: 'CCC', goal: 'yes', lag: "23.3343" }],
    c = [{ id: 36, name: 'AAA', goal: 'yes', color: "purple" }, { id: 40, name: 'BBB', circle: 'yes', color: "purple" }, { id: 100, name: 'JJJ', circle: 'yes' }],
    map = new Map,
    result = [];

[g, c].forEach(function (a) {
    a.forEach(merge);
});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

使用动态密钥。

function mergeBy(key, data) {
    return Array.from(data
        .reduce((m, o) => m.set(o[key], { ...m.get(o[key]), ...o }), new Map)
        .values()
    );
}

var g = [{ id: 36, name: 'AAA', goal: 'yes', 'random': 27 }, { id: 40, name: 'BBB', goal: 'yes' }, { id: 39, name: 'JJJ', goal: 'yes' }, { id: 27, name: 'CCC', goal: 'yes', lag: "23.3343" }],
    c = [{ id: 36, name: 'AAA', goal: 'yes', color: "purple" }, { id: 40, name: 'BBB', circle: 'yes', color: "purple" }, { id: 100, name: 'JJJ', circle: 'yes' }],
    result = mergeBy('id', [...g, ...c]);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }


你能解释一下 r.push(temp) 的作用吗?因为 r 不是一个数组。另外,当我尝试使用更大的数据集时,它只返回最后一个对象,而不是它遍历过的所有对象。我认为这是因为 reduce 只返回单个值。我尝试将 reduce 替换为 map,但也没有起作用。 - Sayran
r 是 reduce 回调函数中的累加器。它的初始值是一个空数组。 - Nina Scholz
当我尝试使用更大的数据集来解决这个问题时,它只返回了最后一个对象,而不是它遍历过的所有对象。我认为这是因为reduce只返回单个值。我尝试用map替换reduce,但也没有起作用。 - Sayran
@Toros91,你可以在键上闭包,并存储返回的函数,然后像merge一样使用它,但是将o.id替换为o[key] - Nina Scholz
1
请查看第三种方法。 - Nina Scholz
显示剩余9条评论

1
这是一个Python解决方案。它修改了“g”,你可能想要或不想要。
c_by_id = {d['id']: d for d in c}
for item in g:
    item.update(c_by_id.get(item['id']), {})

1
我认为OP想要一个JavaScript的解决方案,因为他的尝试表明了这一点。 - 31piy

0

这可以通过下划线函数_.uniq_.union轻松实现。

只需使用以下代码:

var finalData = _.uniq(_.union(c, g),  function (ele)  {
                    return ele.id
                })

这将会返回你所寻找的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接