Hi,
I have these 2 arrays of objects:
const arr1 = [{"id":"pear","qty":2},{"id":"apple","qty":2}];
const arr2 = [{"id":"pear","qty":5},{"id":"lemon","qty":1}];
I want to combine them but at the same time summing their values in qty
when they have the same id
so this is the expected output:
[{"id":"pear","qty":7},{"id":"apple","qty":2},{"id":"lemon","qty":1}];
I tried this but it only keeps the first object:
const newArray = arr1.map((obj) => {
const secondArrayObj = arr2.find((obj2) => obj2.id === obj.id);
if (secondArrayObj) {
return {...secondArrayObj, ...obj}
}
return null;
}).filter((obj) => obj != null);
console.log(newArray);
What is the best approach here?
Thank you.
CodePudding user response:
For your code,the reason is that you are using Array.map()
,it will only covnert arr1
to another array,and will not merge arr2
To solve it,we can do it via Array.reduce()
and Array.filter()
const arr1 = [{"id":"pear","qty":2},{"id":"apple","qty":2}];
const arr2 = [{"id":"pear","qty":5},{"id":"lemon","qty":1}];
let arr3 = [...arr1,...arr2]
arr3 = arr3.reduce((a,v) => {
let obj = a.find(i => i.id === v.id)
if(obj){
obj.qty = v.qty
}else{
a.push(v)
}
return a
},[])
console.log(arr3)
CodePudding user response:
There are several ways to skin the cat. Here is one that uses an intermediate sums
object, which performs well with large arrays:
const arr1 = [{"id":"pear","qty":2},{"id":"apple","qty":2}];
const arr2 = [{"id":"pear","qty":5},{"id":"lemon","qty":1}];
let sums = {};
arr1.concat(arr2).forEach(obj => {
if(!sums[obj.id]) {
sums[obj.id] = 0;
}
sums[obj.id] = obj.qty;
});
let arr3 = Object.keys(sums).map(id => { return {id: id, qty: sums[id]}; });
console.log(arr3);
Output:
[
{
"id": "pear",
"qty": 7
},
{
"id": "apple",
"qty": 2
},
{
"id": "lemon",
"qty": 1
}
]
CodePudding user response:
- Combine both arrays
- Reduce them to an object keyed by
id
and value being the sum ofqty
- Turn that object back into an array using Object.entries()
- Map that back to an array of objects
const arr1 = [{"id":"pear","qty":2},{"id":"apple","qty":2}];
const arr2 = [{"id":"pear","qty":5},{"id":"lemon","qty":1}];
const newArray = Object.entries(
arr1.concat(arr2).reduce(
(map, { id, qty }) => ({
...map,
[id]: qty (map[id] ?? 0),
}),
{}
)
).map(([id, qty]) => ({ id, qty }));
console.log(newArray);
.as-console-wrapper { max-height: 100% !important; }