Reputation: 1172
Here is what I'm trying to do :
I have these 2 arrays as inputs. I want to combine them, and merge the objects that have the same "type" property and for these, add the quantities. So, with these 2 arrays below, I have an object with a "type" equal to veggie in each array. The resulting array would have an object with a "type" veggie, and the associated quantity equal to 30 (27+3).
const arr1 = [{"quantity": 27, "type": "veggie"}, {"quantity": 191, "type": "meat"}, {"quantity": 3, "type": "fruit"}];
const arr2 = [{"quantity": 13, "type": "fish"}, {"quantity": 191, "type": "dairy"}, {"quantity": 3, "type": "veggie"}];
const all = [...arr1, ...arr2];
function mergeArrays(arr) {
const res = arr.reduce(function(acc, curr) {
const findTagIndex = acc.findIndex((item) => item.type === curr.type);
if (findTagIndex === -1) {
acc.push(curr)
} else {
acc[findTagIndex].quantity += curr.quantity
}
return acc;
}, []);
return res;
}
const newArray = mergeArrays(all);
console.log(newArray) // [{quantity: 191, type: "meat"}, {quantity: 30, type: "veggie"}, {quantity: 3, type: "fruit"}, {quantity: 13, type: "fish"}, {quantity: 191, type: "dairy"}];
What I don't understand, and I'm stuck with, is that the merging of arrays seems to mutate arr1
.
If I console log of arr1
before and after getting the newArray
, it will log resp. 27 and 30 veggies. What's going on ?
Any suggestion what I am doing wrong ? How else can I proceed ? I tried several things. I tried with a forEach
. Same result.
Upvotes: 0
Views: 64
Reputation: 38189
It is possible to use reduce
method to calculate sum:
const arr1 = [{"quantity": 27, "type": "veggie"}, {"quantity": 191, "type": "meat"}, {"quantity": 3, "type": "fruit"}];
const arr2 = [{"quantity": 13, "type": "fish"}, {"quantity": 191, "type": "dairy"}, {"quantity": 3, "type": "veggie"}];
const merged = arr1.concat(arr2);
const result = merged.reduce((a, {type, quantity}) => {
a[type] = a[type] || {type, quantity: 0};
a[type].quantity += quantity || 0;
return a;
}, {})
console.log(Object.values(result));
Upvotes: 0
Reputation: 138457
You push the objects from the first array into the other array, thus both arrays hold references to the same objects. You can easily (shallow) copy the objects when pushing:
acc.push({ ...curr });
Here's how I'd do that (in O(n)):
const quantityByType = new Map();
for(const { type, quantity } of [...arr1, ...arr2]) {
amountByType.set(type, quantity + (quantityByType.get(type) || 0));
}
const result = [...quantityByType.entries()]
.map(([type, quantity]) => ({ type, quantity }));
Upvotes: 1