I have two arrays of objects of the same structure. Array 1 contains elements such as:
[
{
id: "1",
name: "XX",
displayName: "XX",
count: 12
},
{
id: "2",
name: "XX",
displayName: "XX",
count: 12
},
{
id: "3",
name: "XX",
displayName: "XX",
count: 12
}
]
Array 2 contains elements such as:
[
{
id: "1",
count: 2
},
{
id: "3",
count: 5
}
]
I need a resulting array of this type:
[
{
id: "1",
name: "XX",
displayName: "XX",
count: 10
},
{
id: "2",
name: "XX",
displayName: "XX",
count: 12
},
{
id: "3",
name: "XX",
displayName: "XX",
count: 7
}
]
That means I need a new array containing all items from array1 with that same structure, but if in array 2 i have a matching ID the new count should be the difference between the value of the two, otherwise it is unchanged. I have been trying to implement this using .reduce() but I am having some trouble getting the logic together, can anyone shed some light on how should I think this through? I am fairly new to JS and I come from a mostly C99 and Python background.
I am excluding the use of nested for loops for this for obvious reasons. A solution I had in mind was to make all the "count" values in in the second array negative, and using this other method I found on this same website. This solution also implies all attributes are int values and sums them all up:
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()]
But that does not feel elegant or "right", and I feel like I should instead focus on understanding methods related to maps a bit better. Can anybody help?
Reduce to an intermediate object and take the values of that:
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);