如何合并两个同类对象的数组,并对某个字段进行操作?

问题描述 投票:0回答:2

我有两个相同结构的对象数组。 数组 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()]

但这感觉并不优雅或“正确”,我觉得我应该专注于更好地理解与地图相关的方法。有人可以帮忙吗?

javascript arrays merge maps
2个回答
0
投票

Reduce 到一个中间对象并取它的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);


0
投票

一种方法是使用

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);

© www.soinside.com 2019 - 2024. All rights reserved.