Reputation: 22520
Suppose i have an array:
const items = [
{
"amount1": "100",
"amount2": "50",
"name": "ruud"
},
{
"amount1": "40",
"amount2": "60",
"name": "ted"
}
]
I want to get all amount1 and amount2 props totalled and result in:
[
{
"amount1": 140,
"amount2": 110
}
]
How can I do this?
Upvotes: 0
Views: 116
Reputation: 136598
reduce()
is indeed the way to go, but the cleanest to go only through a set of known keys is probably to pass your expected result as the accumulator and to iterate over this accumulator's keys:
const items = [
{ amount1: "100", amount2: "50", name: "ruud", foo: "unrelated" },
{ amount1: "40", amount2: "60", name: "ted", foo: "0" }
];
const result = items.reduce((acc, item) => {
for (let key in acc) { // iterate over the accumulator's keys
acc[key] += isNaN(item[key]) ? 0 : +item[key];
}
return acc;
}, { // here we define the expected format
amount1: 0,
amount2: 0
});
console.log(result);
Upvotes: 0
Reputation: 97120
Using Array.prototype.reduce()
with Object.entries()
and Array.prototype.forEach()
:
const items = [{amount1: 100, amount2: 50}, {amount1: 40, amount2: 60}];
const sums = items.reduce((acc, item) => {
Object.entries(item).forEach(([k, v]) => acc[k] = (acc[k] || 0) + v);
return acc;
}, {});
console.log(sums);
To filter out non-number properties (but keep quoted number strings, as per the updated question):
const items = [{amount1: '100', amount2: '50', name: 'Ruud'}, {amount1: '40', amount2: '60', name: 'Ted'}];
const sums = items.reduce((acc, item) => {
Object.entries(item)
.filter(([_, v]) => !isNaN(v))
.forEach(([k, v]) => acc[k] = (acc[k] || 0) + Number(v));
return acc;
}, {});
console.log(sums);
Upvotes: 2
Reputation: 36564
You can use reduce()
.
reduce()
method on the array items
ac
) as an empty object i.e {}
for..in
loop to iterate through all keys of object.typeof
value of key
is "number"
then add it otherwise don'tconst items = [{amount1:100, amount2:50, name:"ruud"}, {amount1:40,amount2:60,name:"ted"}]
let res = [items.reduce((ac,x) => {
for(let key in x){
if(typeof x[key] === "number"){
if(!ac[key]) ac[key] = 0;
ac[key] += x[key]
}
}
return ac;
},{})]
console.log(res)
Upvotes: 0
Reputation: 1618
Above solutions are great. I included this if you don't want to use Array.prototype.reduce(). This will work even if you have other properties which are not "numbers"
const items = [{amount1: 100, amount2: 50, name: 'Ruud'}, {amount1: 40, amount2: 60, name: 'Ted'}];
var result = {};
items.forEach(function(eachItem){
for(var prop in eachItem){
if(typeof eachItem[prop] === "number"){
result[prop] = result[prop] ? result[prop] + eachItem[prop] : eachItem[prop];
}
}
});
result = [result];
console.log(result);
Upvotes: 0
Reputation: 6728
Here is an alternative, simple, and clean solution for this.
const items = [{amount1:100, amount2:50, name:"ruud"},{amount1:40,amount2:60,name:"ted"}]
let result = [{amount1:0,amount2:0}]
items.forEach(i=>{
result[0].amount1 += i.amount1
result[0].amount2 += i.amount2
})
console.log(result)
Upvotes: 0
Reputation: 658
const items = [{amount1: 100, amount2: 50}, {amount1: 40, amount2: 60}];
function sum(data){
const keys = Object.keys(data[0])
let res = {}
for(key of keys)
res[key]=data.map(x=>x[key]).reduce((a,b)=>a+b);
return res
}
console.log(sum(items))
Upvotes: 0