Reputation: 508
I have an array of objects that I want to iterate through and sum some values if the keys exist in the sumList array and average all others. How can we best achieve this?
let sumList = ['TEST1', 'TEST2']
data.forEach(item => {
Object.keys(item).forEach(key => {
if (!result.hasOwnProperty(key)) {
result[key] = 0;
}
if(sumList.includes(key)) {
result[key] += item[key]
} else {
result[key] = (result[key] + item[key]) / 2;
}
});
});
The bug i am running into, i think has to do with the fact that initially value is 0... and it tried to divide 0 + the next value by 2. I would like to do this in the same loop insteam of first summing them then running another loop and averaging them.
Upvotes: 0
Views: 109
Reputation: 2536
You can use reduce()
for the sum, filter()
for the count, then use those two values to calculate the average:
const getValidKey = obj => sumList.find(key=>obj.hasOwnProperty(key));
const sum = data.reduce((accum, currentObj) => {
const key = getValidKey(currentObj);
return key ? accum + currentObj[key] : accum;
}, 0);
const count = data.filter(currentObj=>
getValidKey(currentObj) !== undefined
).length;
const average = sum/count;
There is nothing wrong with iterating through an array twice, as long as there aren't thousands of items. Code readability is more important than improving performance by a few milliseconds.
Upvotes: 1
Reputation: 10627
Should be like:
let sumList = ['TEST1', 'TEST2'], o, n, z, v, results = [];
for(let a of data){
o = {sums:0}; n = 0; z = 0;
for(let o of a){
for(let i in o){
v = o[i];
if(sumList.indexOf(i) === -1){
o.sums += v;
}
else{
z++; n += v;
}
}
}
o.avgs = z === 0 ? 0 : n/z;
results.push(o);
}
Upvotes: 1