使用ES6合并两个对象数组并覆盖现有对象

10

我有两个对象数组:

const arr1 = [{'id':'1' 'value':'yes'}, {'id':'2', 'value':'no'}];
const arr2 = [{'id':'2', 'value':'yes'}];
所以,如果我尝试合并这两个数组,结果应该是:
arrTemp = [{'id':'1', 'value':'yes'}, {'id':'2', 'value':'yes'}];

基本上,它应该和Object.assign()类似,但无论我尝试什么都不起作用。有人能帮我吗?

我修改了数据结构。现在是否可以合并它们并获得输出。

谢谢


你打算如何移除 {'2':'no'}? - moon
2
这个数据结构太丑了。 - Jonas Wilms
你为什么在每个对象中使用不同的键? - charlietfl
9个回答

6
这就是如何使用ES6的展开运算符、reduce和Object.values完成工作。

const arr1 = [{
  'id': '1',
  'value': 'yes'
}, {
  'id': '2',
  'value': 'no'
}];
const arr2 = [{
  'id': '2',
  'value': 'yes'
}];

const result = Object.values([...arr1, ...arr2].reduce((result, {
  id,
  ...rest
}) => {
  result[id] = {
    ...(result[id] || {}),
    id,
    ...rest
  };
  return result;
}, {}));

console.log(result);


1
这真的很棒,是最新的答案,感谢分享! - HKG

3
const result = Object.entries(Object.assign({}, ...arr1,...arr2)).map(([key, value]) => ({[key]:value}));

你可以使用Object.assign方法将这些数组展开成一个对象,然后再对其进行map操作以得到一个新的数组。


它抛出了uncaughtException: Unexpected token : 。我同意数据结构很丑,但现在无法更改。 - Ashy Ashcsi
@ashy 不好意思,已经修复了 ;) - Jonas Wilms

2
在JavaScript中,数组只是从0开始索引的数字对象。因此,当您在arr1和arr2上使用Object.assign时,您将用arr2中的第一个项覆盖arr1中的第一个项,因为它们都在键0下索引。你的结果将是:
[
 { '2': 'yes' },
 { '2': 'no' }
]

(或者以对象语法表示:)
{ 
 0: { '2': 'yes' },
 1: { '2': 'no' }
}

不使用数组,你可以创建一个以数字字符串为索引的对象(无论如何,这似乎是你对数组的想法)。

所以,你可以更改原始数据结构,使工作更容易:

const arr1 = {
  '1': 'yes',
  '2': 'no'
};

const arr2 = {
  '2': 'yes'
};

const result = Object.assign(arr1, arr2);

1
为什么不直接使用 { 1: "是", 2: "否" } 呢?通常情况下,我更喜欢在JavaScript中使用对象而不是数组。 -> 这是错误的方法,请根据具体情况选择正确的方法。数组非常非常有用。 - Jonas Wilms
这是一个非常大的对象数组。 - Ashy Ashcsi

2
您可以使用有效的ES6数据结构,例如Map:
``` const map1 = new Map(); map1.set(1, { string: 'yes' }); map1.set(2, { string: 'no' });
const map2 = new Map(); map2.set(2, { string: 'yes' }); map2.set(3, { string: 'no' });
const mergedMap = new Map([...map1, ...map2]); ```
这将覆盖第一个参数与第二个参数,或在可能的情况下将它们合并。您可以在浏览器中尝试一下,这样做更容易,而且能够提高性能,因为您将不再需要使用昂贵的`findById()`操作。

findById() -> 这应该是什么?!而且标识符不能以数字开头! - Jonas Wilms

0

您可以将Map作为结果数组中新分配对象的参考,并首先使用对象的副本构建一个新数组,然后迭代第二个数组并使用相同的键更新对象。

var array1 = [{ 1: 'yes' }, { 2: 'no' }],
    array2 = [{ 2: 'yes' }],
    getKey = o => Object.keys(o)[0],
    map = new Map,
    result = array1.map(o => (k => map.set(k, Object.assign({}, o)).get(k))(getKey(o)));

array2.forEach(o => Object.assign(map.get(getKey(o)), o));

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


0

在编程中,数组的reduce方法可能会派上用场。请参考下面的示例:

[...arr1, ...arr2].reduce((acc, item) => {
  const updated = acc.find(a => a.id === item.id)
  if (!updated) {
    acc.push(item)
  } else {
    const index = acc.indexOf(updated)
    acc[index] = { ...item, ...acc[index] }
  }
  return acc
}, [])

-1

对于任何在以后时间点找到这个答案的人。有几种方式可以让它正常工作,但你可以过滤第一个数组中所有已调整的元素,然后将其与第二个数组组合。

const arr3 = [...arr1.filter(item1 => !arr2.find(item2 => item1.id === item2.id)), ...arr2]

或者,您可以更新第一个数组中的元素,然后从第二个数组中过滤它们。


-1

添加已存在的对象数组的简单方法:

const arr1 = [{ "name":"John", "age":30, "car":"toyata" }];
const arr2 = [{ "name":"Ales", "age":40, "car":"Nissan" }];
Array.prototype.push.apply(arr1, arr2);

Result:=>
console.log(arr1)

-2

你不能使用array.prototype map,因为arr1和arr2的键具有相同的值“2”。

你应该使用类似这样的东西

for (var i = 0, l = arr1.length; i < l; i++) {
 var key = Object.keys(arr1[i]);
 if (!arr2[key]) { arr2[key] = []; }
 arr2[key].push(arr1[i][key]);
}

敬礼


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