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?
2
Answers
One method is to use
Array#map
to create the array with updated counts andArray#find
to get the matching element by id from the second array (if any) on each iteration.A more efficient method would be to first create an object that maps each id in the second array to its count, then use those counts when generating the new array.
Reduce to an intermediate object and take the values of that: