【问题标题】:Merge two array of objects with same keys, some object won't have the same value?合并两个具有相同键的对象数组,某些对象不会具有相同的值?
【发布时间】:2018-05-22 15:47:49
【问题描述】:

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

最好在 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

【问题讨论】:

标签: javascript python arrays object


【解决方案1】:

您可以使用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,它也不起作用。
  • r 是 reduce 回调的累加器。它有一个空数组作为初始值。
  • 当我用更大的数据集尝试这个解决方案时,它只返回最后一个对象,而不是它循环通过的所有对象。我在想它是因为 reduce 只返回一个值。我用地图切换了reduce,它也不起作用
  • 它总是返回所有合并的对象。版本 2 现在无需减少即可工作。
  • 请参阅第三种方法。
【解决方案2】:

这是一个 Python 解决方案。这会修改 g,您可能想要也可能不想要。

c_by_id = {d['id']: d for d in c}
for item in g:
    item.update(c_by_id.get(item['id']), {})

【讨论】:

  • 我认为 OP 想要一个 JavaScript 解决方案,因为他的尝试表明了这一点。
【解决方案3】:

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

就用这个吧:

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

这将返回您正在寻找的内容。

【讨论】:

    猜你喜欢
    • 2018-01-13
    • 2019-03-05
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    • 2021-06-05
    相关资源
    最近更新 更多