我想合并两个对象数组,其中具有相同ID的对象将合并属性,而具有唯一ID的对象将成为 merged 数组中自己的对象。以下代码在第一部分中将合并相似的ID,但是如何将具有 arr2 中唯一ID的对象保留在合并数组中,并使其与可变长度的数组一起使用?
预期输出:
[
{
"id": "1",
"date": "2017-01-24",
"name": "test"
},
{
"id": "2",
"date": "2017-01-22",
"bar": "foo"
}
{ "id": "3",
"foo": "bar",
}
]
代码:
let arr1 = [{
id: '1',
createdDate: '2017-01-24'
},
{
id: '2',
createdDate: '2017-01-22'
},
];
let arr2 = [{
id: '1',
name: 'test'
},
{
id: '3',
foo: 'bar'
},
{
id: '2',
bar: 'foo'
},
];
let merged = [];
for (let i = 0; i < arr1.length; i++) {
merged.push({
...arr1[i],
...arr2.find((itmInner) => itmInner.id === arr1[i].id),
},
);
}
console.log(merged);
答案 0 :(得分:1)
依次遍历较大的数组,该数组包含较小的数组,
let arr1=[{id:"1",createdDate:"2017-01-24"},{id:"2",createdDate:"2017-01-22"}],arr2=[{id:"1",name:"test"},{id:"3",foo:"bar"},{id:"2",bar:"foo"}];
const merged = arr2.map(item => ({
...arr1.find(({ id }) => id === item.id),
...item
}));
console.log(merged);
(如果顺序很重要,那么以后也可以排序)
如果您事先不知道哪个/如果一个包含另一个,则使用一个对象首先按ID索引合并的对象:
let arr1=[{id:"1",createdDate:"2017-01-24"},{id:"2",createdDate:"2017-01-22"}],arr2=[{id:"1",name:"test"},{id:"3",foo:"bar"},{id:"2",bar:"foo"}];
const resultObj = Object.fromEntries(
arr1.map(
item => [item.id, { ...item }]
)
);
for (const item of arr2) {
if (!resultObj[item.id]) {
resultObj[item.id] = item;
} else {
Object.assign(resultObj[item.id], item);
}
}
const merged = Object.values(resultObj);
console.log(merged);
答案 1 :(得分:0)
您可以按以下方法创建包含arr1
和arr2
组元素的新对象,方法是按id
键,合并的数组将存储在对象值上。
您可以使用Object.values
函数获取对象值。
let arr1 = [{
id: '1',
createdDate: '2017-01-24'
},
{
id: '2',
createdDate: '2017-01-22'
},
];
let arr2 = [{
id: '1',
name: 'test'
},
{
id: '3',
foo: 'bar'
},
{
id: '2',
bar: 'foo'
},
];
const groupById = {};
for (let i = 0; i < Math.min(arr1.length, arr2.length); i ++) {
if (arr1[i]) {
groupById[arr1[i].id] = { ...groupById[arr1[i].id], ...arr1[i] };
}
if (arr2[i]) {
groupById[arr2[i].id] = { ...groupById[arr2[i].id], ...arr2[i] };
}
}
const merged = Object.values(groupById);
console.log(merged);
答案 2 :(得分:0)
通过将对象存储在哈希表中(按id
排序),可以采用单循环方法。
const
mergeTo = (target, objects = {}) => o => {
if (!objects[o.id]) target.push(objects[o.id] = {});
Object.assign(objects[o.id], o);
},
array1 = [{ id: '1', createdDate: '2017-01-24' }, { id: '2', createdDate: '2017-01-22' }],
array2 = [{ id: '1', name: 'test' }, { id: '3', foo: 'bar' }, { id: '2', bar: 'foo' }],
merged = [],
merge = mergeTo(merged);
array1.forEach(merge);
array2.forEach(merge);
console.log(merged);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 3 :(得分:0)
另一种方法可以按原样合并两个数组,然后“压缩”它:
let arr1 = [{
id: '1',
createdDate: '2017-01-24'
},
{
id: '2',
createdDate: '2017-01-22'
},
];
let arr2 = [{
id: '1',
name: 'test'
},
{
id: '3',
foo: 'bar'
},
{
id: '2',
bar: 'foo'
},
];
let merged = [...arr1, ...arr2].reduce(
(acc, {id, ...props}) =>
(acc.set(id, {...(acc.get(id) || {}), ...props}), acc), new Map());
console.log([...merged].map( ([id, props]) => ({id, ...props}) ))
请注意,您可能不需要最后一行,它仅用于获取所需的格式,因为上述reduce使用Map作为累加器,您已经可以使用例如merged.get("1").createdDate
(其中"1"
是ID)。
由于您在一开始就通过合并它们来处理一个数组,因此您不必在意它们的长度,甚至也不关心其中包含更多元素的数组。您也可以有多个数组而不是只有两个,这没关系。
重要的是顺序:如果一个以上的数组包含相同的“ id”属性,则您获得的值就是最近添加的数组中的值(在上面的示例中,将为{ {1}}。
答案 4 :(得分:0)
您可以编写函数以将数组简化为一个对象,然后从该对象中提取值,这将返回所需的值。您可以看到以下代码:
let arr1 = [
{
id: '1',
createdDate: '2017-01-24',
},
{
id: '2',
createdDate: '2017-01-22',
},
];
let arr2 = [
{
id: '1',
name: 'test',
},
{
id: '3',
foo: 'bar',
},
{
id: '2',
bar: 'foo',
},
];
function merge(arr1 = [], arr2 = []) {
return Object.values(
arr1.concat(arr2).reduce(
(acc, curr) => ({
...acc,
[curr.id]: { ...(acc[curr.id] ?? {}), ...curr },
}),
{}
)
);
}
const merged = merge(arr1, arr2);
输出:
[
{
"id": "1",
"createdDate": "2017-01-24",
"name": "test"
},
{
"id": "2",
"createdDate": "2017-01-22",
"bar": "foo"
},
{
"id": "3",
"foo": "bar"
}
]