HeelMega
HeelMega

Reputation: 508

Iterate through array and average/sum values in it

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

Answers (2)

Ro Milton
Ro Milton

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;

Live Demo

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

StackSlave
StackSlave

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

Related Questions