我有两个相同结构的对象数组。 数组 1 包含以下元素:
[
{
id: "1",
name: "XX",
displayName: "XX",
count: 12
},
{
id: "2",
name: "XX",
displayName: "XX",
count: 12
},
{
id: "3",
name: "XX",
displayName: "XX",
count: 12
}
]
数组 2 包含如下元素:
[
{
id: "1",
count: 2
},
{
id: "3",
count: 5
}
]
我需要这种类型的结果数组:
[
{
id: "1",
name: "XX",
displayName: "XX",
count: 10
},
{
id: "2",
name: "XX",
displayName: "XX",
count: 12
},
{
id: "3",
name: "XX",
displayName: "XX",
count: 7
}
]
这意味着我需要一个包含 array1 中具有相同结构的所有项目的新数组,但是如果在数组 2 中我有一个匹配的 ID,则新计数应该是两者值之间的差值,否则它是不变的。 我一直在尝试使用 .reduce() 来实现这个,但是我在整理逻辑时遇到了一些麻烦,任何人都可以阐明我应该如何思考这个问题吗?我是 JS 的新手,我主要来自 C99 和 Python 背景。
出于显而易见的原因,我排除了嵌套 for 循环的使用。 我想到的一个解决方案是使第二个数组中的所有“计数”值都为负数,并使用我在这个same 网站 上找到的其他方法。该解决方案还暗示所有属性都是 int 值并将它们全部加起来:
const sumItem = ({ id, ...a }, b) => ({
id,
...Object.keys(a)
.reduce((r, k) => ({ ...r, [k]: a[k] + b[k] }), {})
});
const sumObjectsByKey = (...arrs) => [...
[].concat(...arrs) // combine the arrays
.reduce((m, o) => // retuce the combined arrays to a Map
m.set(o.id, // if add the item to the Map
m.has(o.id) ? subItem(m.get(o.id), o) : { ...o } // if the item exists in Map, sum the current item with the one in the Map. If not, add a clone of the current item to the Map
)
, new Map).values()]
但这感觉并不优雅或“正确”,我觉得我应该专注于更好地理解与地图相关的方法。有人可以帮忙吗?
const array1 = [{
id: "1",
name: "XX",
displayName: "XX",
count: 12
}, {
id: "2",
name: "XX",
displayName: "XX",
count: 12
}, {
id: "3",
name: "XX",
displayName: "XX",
count: 12
}];
const array2 = [{
id: "1",
count: 2
}, {
id: "3",
count: 5
}];
const result = Object.values([...array1, ...array2].reduce((a, v) => {
if (a[v.id]) a[v.id].count -= v.count
else a[v.id] = { ...v }
return a;
}, {}));
console.log(result);
一种方法是使用
Array#map
创建具有更新计数的数组,并使用 Array#find
在每次迭代中通过 id 从第二个数组(如果有)获取匹配元素。
let arr1=[{id:"1",name:"XX",displayName:"XX",count:12},{id:"2",name:"XX",displayName:"XX",count:12},{id:"3",name:"XX",displayName:"XX",count:12}],
arr2=[{id:"1",count:2},{id:"3",count:5}];
let res = arr1.map(o => ({...o, count : o.count -
(arr2.find(x => o.id === x.id)?.count ?? 0)}));
console.log(res);
一种更有效的方法是首先创建一个对象,将第二个数组中的每个 id 映射到它的计数,然后在生成新数组时使用这些计数。
let arr1=[{id:"1",name:"XX",displayName:"XX",count:12},{id:"2",name:"XX",displayName:"XX",count:12},{id:"3",name:"XX",displayName:"XX",count:12}],
arr2=[{id:"1",count:2},{id:"3",count:5}];
let counts2 = arr2.reduce((acc, curr) => {
acc[curr.id] = curr.count;
return acc;
}, {});
let res = arr1.map(o => ({...o, count : o.count - (counts2[o.id] ?? 0)}));
console.log(res);