javascript在平均计算中排除一些值

时间:2019-05-22 18:34:03

标签: javascript arrays javascript-objects

以下是一些数据:

data = [
 {"Age":26,"Level":8},
 {"Age":37,"Level":9},
 {"Age":null,"Level":15},
 {"Age":null,"Level":45}
];

我试图从中计算其属性的平均值:

var avg = {};
  var rows = data.length;
  data.forEach(obj => {
      Object.keys(obj).forEach(k => {
        if(obj[k] != null){
          avg[k] = (avg[k] || 0) + obj[k] / rows;
        }
      });
    });

  return avg;

但是问题出在具有null值的属性的项目中,我试图从计算中排除null值,如果您查看{{3} }年龄: 15.75 ,而不是 31.5 因为数据的长度始终为4(并且应为2,因为其中2个为null)。如何使长度不包括null的最佳方法是什么?

6 个答案:

答案 0 :(得分:1)

您可以使用简单的for...offor...in循环为每个非空项目获取sumcount。您可以添加get属性,以根据计数器中的sumcount属性自动计算平均值

const data = [{Age:26,Level:8},{Age:37,Level:9},{Age:null,Level:15},{Age:null,Level:45}];

let counter = {}

for (const item of data) {
  for (const key in item) {
    if (item[key] !== null) {
        counter[key] = counter[key] || {
          sum: 0,
          count: 0,
          get average() { return this.sum/this.count }
        };
        counter[key].sum += item[key]
        counter[key].count++
      }
    }
  }

  console.log(counter)

答案 1 :(得分:1)

您可以分别存储每个键的总和和计数。

var data = [{ "Age": 26, "Level": 8 }, { "Age": 37, "Level": 9 }, { "Age": null, "Level": 15 }, { "Age": null, "Level": 45 }],
    avg = {},
    temp = {};

data.forEach(obj => Object.keys(obj).forEach(k => {
    if (obj[k] === null) return;
    temp[k] = temp[k] || { sum: 0, count: 0 };
    temp[k].sum += obj[k];
    temp[k].count++;
    avg[k] = temp[k].sum / temp[k].count;
}));

console.log(avg);
console.log(temp);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:1)

您可以使用带有嵌套对象的对象,该对象具有两个属性valuecount

const data = [
 {"Age":26,"Level":8},
 {"Age":37,"Level":9},
 {"Age":null,"Level":15},
 {"Age":null,"Level":45}
];

let avg = {}

data.forEach(x => {
  for(let k in x){
    if(!avg[k]){
      avg[k] = {value:0,count:0};
    }
    if(x[k] !== null){
      avg[k].value += x[k]
      avg[k].count++;
    }
  }
})

avg = Object.fromEntries(Object.entries(avg).map(([k,v]) => ([k,v.value/v.count])))

console.log(avg)

答案 3 :(得分:1)

let data = [
	{"Age": 26, "Level": 8},
	{"Age": 37, "Level": 9},
	{"Age": null, "Level": 15},
	{"Age": null, "Level": 45}
];

let averages = data.reduce((values, o) => {
	Object.entries(o).forEach(([k, v]) => {
		if (v !== null)
			values[k] = (values[k] || []).concat(v);
	});
	return values;
}, {});

Object.entries(averages).forEach(([k, vs]) =>
	averages[k] = vs.reduce((a, b) => a + b) / vs.length);

console.log(averages);

答案 4 :(得分:1)

我会做这样的事情:(尚未测试)

var data = [
    {"Age":26,"Level":8},
    {"Age":37,"Level":9},
    {"Age":null,"Level":15},
    {"Age":null,"Level":45}
];

var sum = { "Age": 0, "Level": 0 };
var average = { "Age": 0, "Level": 0 };
var sumCount = { "Age": 0, "Level": 0 };

// sum up all objects
for (var i = 0; i < data.length; i++) {
    Object.keys(data[i]).forEach(function (key) {
        if (data[i][key] == null || data[i][key] == undefined)
            return;
        sumCount[key]++;
        sum[key] = sum[key] + data[i][key];
    });
}

// make average object
Object.keys(average).forEach(function (key) {
    average[key] = sum[key] / sumCount[key];
});

答案 5 :(得分:0)

您也可以只用Array.reduce来以相对简洁的方式进行操作,而在其内部只需遍历Object.keys

var data = [ {"Age":26,"Level":8}, {"Age":37,"Level":9}, {"Age":null,"Level":15}, {"Age":null,"Level":45} ];

let result = data.reduce((r, c) => (Object.keys(c).forEach(k => {
    r[k] = (r[k] || { Sum: 0, Count: 0, Avg: 0 })
    r[k].Sum += c[k] || 0
    r[k].Count += c[k] ? 1 : 0
    r[k].Avg = r[k].Sum / r[k].Count
  }), r), {})

console.log(result)