如何唯一地合并两个对象数组?

时间:2018-01-21 19:04:03

标签: javascript arrays lodash

我试图合并两个对象数组而不使用lodash中的unionBy方法。

目前,我有以下代码可以正常运行:

var array1 = [
 { a: 1, b: 'first'},
 { a: 2, b: 'second'}
];

var array2 = [
 { a: 3, b: 'third'},
 { a: 1, b: 'fourth'}
];

var array3 = __.unionBy(array2, array1, 'a');

输出:

[
  {
    "a": 3,
    "b": "third"
  },
  {
    "a": 1,
    "b": "fourth"
  },
  {
    "a": 2,
    "b": "second"
  }
]

这是理想的结果,但我无法在当前的工作环境中使用unionBy,因此我正在寻找使用原生JS或其他lodash方法3.6.0的结果或低。

6 个答案:

答案 0 :(得分:2)

Concat并使用Array#filter和辅助对象删除重复项:



var array1 = [{"a":1,"b":"first"},{"a":2,"b":"second"}];

var array2 = [{"a":3,"b":"third"},{"a":1,"b":"fourth"}];

var result = array2.concat(array1).filter(function(o) {  
  return this[o.a] ? false : this[o.a] = true;
}, {});

console.log(result);




如果ES6是一个选项,您可以使用Set代替辅助对象:



const array1 = [{"a":1,"b":"first"},{"a":2,"b":"second"}];

const array2 = [{"a":3,"b":"third"},{"a":1,"b":"fourth"}];

const result = array2.concat(array1).filter(function(o) {  
  return this.has(o.a) ? false : this.add(o.a);
}, new Set());

console.log(result);




答案 1 :(得分:1)

您可以使用Set进行过滤以获取唯一值。

var array1 = [{ a: 1, b: 'first' }, { a: 2, b: 'second' }],
    array2 = [{ a: 3, b: 'third' }, { a: 1, b: 'fourth' }],
    s = new Set,
    array3 = array2.map(o => (s.add(o.a), o)).concat(array1.filter(o => !s.has(o.a)));

console.log(array3);

答案 2 :(得分:1)

您可以使用ES6地图。使用a属性值键入的数据构造它,然后再次从Map中取出值:

var array1 = [{"a":1,"b":"first"},{"a":2,"b":"second"}],
    array2 = [{"a":3,"b":"third"},{"a":1,"b":"fourth"}];

var result = [...new Map([...array1,...array2].map( o => [o.a, o] )).values()];

console.log(result);

答案 3 :(得分:0)

您可以合并2个数组,然后过滤具有相同属性a的数组:

var array1 = [{ a: 1, b: 'first'},{ a: 2, b: 'second'}],
  array2 = [{ a: 3, b: 'third'},{ a: 1, b: 'fourth'}],
  array3 = [...array2, ...array1].filter((item, pos, arr) =>
    arr.findIndex(item2 => item.a == item2.a) == pos);

console.log(array3)

如果你仍然想要指定要联合的属性,你可以实现你自己的函数:

var array1 = [{ a: 1, b: 'first'},{ a: 2, b: 'second'}],
  array2 = [{ a: 3, b: 'third'},{ a: 1, b: 'fourth'}],
  array3 = unionBy(array1, array2, 'a');

function unionBy(array1, array2, prop){
  return [...array2, ...array1].filter((item, pos, arr) =>
      arr.findIndex(item2 => item[prop] == item2[prop]) == pos);
}

console.log(array3);

注意:我对一些答案的回答的一个优点是它保留了lodash中的顺序,这可能是也可能不重要。

答案 4 :(得分:0)

使用Array.filterArray.find

的ES5

var array1 = [{ a: 1, b: "first" }, { a: 2, b: "second" }];

var array2 = [{ a: 3, b: "third" }, { a: 1, b: "fourth" }];

function merge(a, b, prop) {
  var reduced = a.filter(function(itemA) {
return !b.find(function(itemB) {
  return itemA[prop] === itemB[prop];
});
  });
  return reduced.concat(b);
}

console.log(merge(array1, array2, "a"));

ES6箭头功能

var array1 = [{ a: 1, b: "first" }, { a: 2, b: "second" }];

var array2 = [{ a: 3, b: "third" }, { a: 1, b: "fourth" }];

function merge(a, b, prop) {
  const reduced = a.filter(
itemA => !b.find(itemB => itemA[prop] === itemB[prop])
  );
  return reduced.concat(b);
}

console.log(merge(array1, array2, "a"));

另一个ES6单行实验

var array1 = [{ a: 1, b: "first" }, { a: 2, b: "second" }];

var array2 = [{ a: 3, b: "third" }, { a: 1, b: "fourth" }];

const merge = (a, b, p) => a.filter( aa => ! b.find ( bb => aa[p] === bb[p]) ).concat(b);

console.log(merge(array1, array2, "a"));

答案 5 :(得分:0)

你可以巧妙地使用 ES6 的 find 和 reduce 功能!

var array1 = [{"a":1,"b":"first"},{"a":2,"b":"second"}];
var array2 = [{"a":3,"b":"third"},{"a":1,"b":"fourth"}];
var res = array1.concat(array2).reduce((aggr, el)=>{
    if(!aggr.find(inst=>inst.a==el.a))
        return [...aggr, el];
    else
        return aggr
},[])

console.log(res);