Javascript 求数组数据的平均值
我一直在研究如何用Javascript实现这个相对简单的操作: 我有一个这样定义的对象列表:Javascript 求数组数据的平均值,javascript,arrays,algorithm,average,Javascript,Arrays,Algorithm,Average,我一直在研究如何用Javascript实现这个相对简单的操作: 我有一个这样定义的对象列表: [ {id: 1, region: "America", country:"USA", values:[1,2,3,4] }, {id: 2, region: "America", country:"Canada", values:[3,4,5,6] }, {id: 3, region: "Europe", country:"France", values:[1,2,3,4] }
[
{id: 1, region: "America", country:"USA", values:[1,2,3,4] },
{id: 2, region: "America", country:"Canada", values:[3,4,5,6] },
{id: 3, region: "Europe", country:"France", values:[1,2,3,4] },
{id: 4, region: "Europe", country:"Italy", values:[1,2,3,4] },
{id: 5, region: "Europe", country:"Spain", values:[5,9,1,7] },
{id: 6, region: "Europe", country:"Germany", values:[1,6,2,8] },
{id: 7, region: "Europe", country:"Ireland", values:[6,4,6,9]}
]
我试图对值字段中包含的数字进行平均,按区域分组。
因此,在上面的列表中,我还有两个元素,一个用于美国,一个用于欧洲,包含平均值:
[
{id: 1, region: "America", country:"USA", values:[1,2,3,4] },
{id: 2, region: "America", country:"Canada", values:[3,4,5,6] },
{id: 3, region: "Europe", country:"France", values:[1,2,3,4] },
{id: 4, region: "Europe", country:"Italy", values:[1,2,3,4] },
{id: 5, region: "Europe", country:"Spain", values:[5,9,1,7] },
{id: 6, region: "Europe", country:"Germany", values:[1,6,2,8] },
{id: 7, region: "Europe", country:"Ireland", values:[6,4,6,9]},
{id: 8, region: "America", country:"avg", values:[2,3,4,5]},
{id: 9, region: "Europe", country:"avg", values:[2.8,4.6,2.8,6.4]}
]
你知道怎么做吗?
请记住,要聚合的元素数可能约为10~15,值字段中的数字可能约为150~200
“值”字段包含所有元素的相同数量的值。
有些值可能为null,因此在这种情况下,我需要计算平均值,因为null不是0
我可以做很多循环来扫描所有东西并进行计算,但我想知道是否有更简单、更快的方法来保持良好的性能
解释/示例:
美国的第一个平均值计算如下:
(sum of first value of 'values' for each country with region 'America')
-----------------------------------------------------------------------
(number of countries with region 'America')
伪代码:
America.avg.values[0] = (USA.values[0] + Canada.values[0]) / 2 /*(1+3)/2 = 2*/;
America.avg.values[1] = (USA.values[1] + Canada.values[1]) / 2 /*(2+4)/2 = 3*/;
...
我只需在整个数组中循环并计算值的平均值,然后在数组中添加一个
avg
属性
var数据=[
{id:1,地区:“美国”,国家:“美国”,价值观:[1,2,3,4]},
{id:2,地区:“美国”,国家:“加拿大”,价值观:[3,4,5,6]},
{id:3,区域:“欧洲”,国家:“法国”,价值观:[1,2,3,4]},
{id:4,区域:“欧洲”,国家:“意大利”,价值观:[1,2,3,4]},
{id:5,区域:“欧洲”,国家:“西班牙”,价值观:[5,9,1,7]},
{id:6,区域:“欧洲”,国家:“德国”,价值观:[1,6,2,8]},
{id:7,区域:“欧洲”,国家:“爱尔兰”,价值观:[6,4,6,9]}
];
forEach(函数(元素、索引、数组){
var总和=0;
element.values.forEach(函数(元素、索引、数组){
总和+=元素;
});
element.avg=总和/element.values.length;
});
控制台日志(数据)代码>您可以使用对象来保持元素的总和和计数,并将每个循环的平均值分配给分组对象
var data=[{id:1,地区:“美国”,国家:“美国”,值:[1,2,3,4]},{id:2,地区:“美国”,国家:“加拿大”,值:[3,4,5,6]},{id:3,地区:“欧洲”,国家:“法国”,值:[1,2,3,4]},{id:4,地区:“欧洲”,国家:“意大利”,值:[1,2,3,4]},{id:5,地区:“欧洲”,国家:“西班牙”,值:[5,9,1,7]},{id:6,地区:“欧洲”,国家:“德国”,价值观:[1,6,2,8]},{id:7,地区:“欧洲”,国家:“爱尔兰”,价值观:[6,4,6,9]};
data.forEach(函数(a,i,aa){
如果(!此[a.区域]){
这个[a.region]={sum:[],count:[],value:[]};
aa.push({id:aa.length+1,region:a.region,country:'avg',value:this[a.region].values});
}
a、 forEach(函数(b,i){
如果(b!==null){
这个[a.区域].sum[i]=(这个[a.区域].sum[i]| | 0)+b;
此[a.region].count[i]=(此[a.region].count[i]| | 0)+1;
此[a.region]。值[i]=此[a.region]。和[i]/此[a.region]。计数[i];
}
},这个);
},Object.create(null));
console.log(数据);
。作为控制台包装{max height:100%!important;top:0;}
您可以这样做:
var data=[{id:1,地区:“美国”,国家:“美国”,值:[1,2,null,4]},{id:2,地区:“美国”,国家:“加拿大”,值:[3,4,5,6]},{id:3,地区:“欧洲”,国家:“法国”,值:[1,2,3,4]},{id:4,地区:“欧洲”,国家:“意大利”,值:[1,2,3,4]},{id:5,地区:“欧洲”,国家:“西班牙”,价值观:[5,9,1,7]},{id:6,地区:“欧洲”,国家:“德国”,价值观:[1,6,2,8]},{id:7,地区:“欧洲”,国家:“爱尔兰”,价值观:[6,4,6,9]}]
//因此区域是可配置的
var地区=[‘美国’、‘欧洲’];
var结果=[];
//对于数据未按id排序的情况。
var lastIndex=Math.max.apply(null,data.map(函数(x){return x.id}))
regions.forEach(函数(r){
var-val=[];
data.forEach(函数(c,i){
如果(c.region===r&&c.values&&c.values.length>0){
c、 forEach(函数(v,i){
如果(!v&&v!==0)返回
val[i]=(val[i]| |[]);
val[i]。推送(v)
})
}
});
var avg=val.map(函数(v){
返回(v.reduce(函数(p,c){returnp+c})/v.length);
})
//不推入数据以防止额外的迭代
结果:推({
id:++lastIndex,
地区:r,
国家:'平均',
数值:平均值
})
});
data=data.concat(结果)
console.log(数据)
减少原始数据,跟踪对象中的中间结果:
- 对象为它遇到的每个新区域生成一个新的关键点
- 当考虑区域的第一个数据输入时,存储两件事:
- 平均值,以第一项值的副本开始
- 平均值表示的计数,从1开始
- 当第二项或第n项出现时,使用移动平均公式计算新的平均值
- 返回结果对象,直到处理完所有条目
- 将对象转换为两个数据点,并将它们合并为原始阵列
var数据=[
{id:1,地区:“美国”,国家:“美国”,值:[1,2,null,4]},
{id:2,地区:“美国”,国家:“加拿大”,价值观:[3,4,5,6]},
{id:3,区域:“欧洲”,国家:“法国”,价值观:[1,2,3,4]},
{id:4,区域:“欧洲”,国家:“意大利”,价值观:[1,2,3,4]},
{id:5,区域:“欧洲”,国家:“西班牙”,价值观:[5,9,1,7]},
{id:6,区域:“欧洲”,国家:“德国”,价值观:[1,6,2,8]},
{id:7,区域:“欧洲”,国家:“爱尔兰”,价值观:[6,4,6,9]}
];
var avg=数据.reduce(函数(结果,当前){
如果(结果[当前区域]){
var obj=结果[当前区域];
obj.avg=当前值
//映射到移动平均线:
//-位置“i”处的当前平均值表示“计数”样本
.map(函数(v,i){
var data = // your array here
function getArr(data,reg) {
return data.filter(el => el.region === reg)
.map(el => el.values)
}
const xpose = x => x[0].map( (c,i) => x.map( r => r[i] ) )
function avgArr(a) {
a = a.filter(el => el !== null);
return a.reduce((x,y) => x+y) / a.length;
}
function calcAverages(data) {
let i = 1 + Math.max.apply(null, data.map( el => el.id )) // max id
let regions = [...new Set (data.map (a => a.region))] // unique regions
regions.forEach( region => {
data.push( { id: i++,
region: region,
country: "avg",
values: xpose(getArr(data,region)).map(a => avgArr(a))})})
return data
}
// > calcAverages(data)
//
// ...
// { id: 8,
// region: 'America',
// country: 'avg',
// values: [ 2, 3, 4, 5 ] },
// { id: 9,
// region: 'Europe',
// country: 'avg',
// values: [ 2.8, 4.6, 3, 6.4 ] } ]