简体   繁体   English

如何计算对象数组中给定属性的JavaScript平均值

[英]How to calculate the average in JavaScript of the given properties in the array of objects

I have an array of objects. 我有一个对象数组。 Each object contains a few properties and one of these properties is age. 每个对象包含一些属性,其中一个属性是age。

var people = [
  {
    name: 'Anna',
    age: 22
  },
  {
    name: 'Tom',
    age: 34
  }, {
    name: 'John',
    age: 12
  },
]

I want to calculate the average for all the age properties in this array. 我想计算这个数组中所有年龄属性的平均值。 I use this function: 我用这个函数:

let getAverage = arr => {
  let reducer = (total, currentValue) => total + currentValue;
  let sum = arr.reduce(reducer)
  return sum / arr.length;
}

It works fine for the simple array like [22, 34, 12] but it does not for the arrays of objects. 它适用于像[22,34,12]这样的简单数组,但不适用于对象数组。

How to modify my getAverage function to make it works also with arrays of object? 如何修改我的getAverage函数,使其也可以与对象数组一起使用?

Here is the snippet with my code: https://jsfiddle.net/marektchas/kc8Ls0f5/2/ 以下是我的代码片段: https//jsfiddle.net/marektchas/kc8Ls0f5/2/

You can use reduce() and add property age of each object in array to ac . 您可以使用reduce()并将数组中每个对象的属性age添加到ac Don't forget to pass 0 (initial value of ac ) as second argument otherwise it would return NaN 不要忘记传递0ac初始值)作为第二个参数,否则它将返回NaN

 var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ] let avgs = people.reduce((ac,a) => a.age + ac,0)/people.length console.log(avgs) 

You don't need to modify getAverage - you can pre-process the array before handing it off, in which case getAverage will work exactly as needed: 您不需要修改getAverage - 您可以在将其关闭之前对数组进行预处理,在这种情况下, getAverage将完全按照需要工作:

 var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ] let getAverage = arr => { let reducer = (total, currentValue) => total + currentValue; let sum = arr.reduce(reducer) return sum / arr.length; } let ages = people.map(person => person.age); console.log(getAverage(ages)); 

If you want to change getAverage , so it can handle any potential type of input, then you can add an optional argument that will perform value extraction, so you don't have to run a map on each array. 如果要更改getAverage ,那么它可以处理任何可能的输入类型,那么您可以添加一个可执行值提取的可选参数,因此您不必在每个数组上运行map

 var numbers = [ 1, 2, 3, 4, 5 ] var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ] var moreComplexObjects = [ { a: { b: { c: 6 } } }, { a: { b: { c: 7 } } }, { a: { b: { c: 8 } } } ] //the default value of the second parameter is a function that returns the input let getAverage = (arr, valueExtractor = x => x) => { //extract the value of each element let reducer = (total, currentValue) => total + valueExtractor(currentValue); let sum = arr.reduce(reducer, 0) //make sure you add an initialiser return sum / arr.length; } const ageExtractor = person => person.age; const complexKeyExtractor = obj => obj.abc; console.log(getAverage(numbers)); console.log(getAverage(people, ageExtractor)); console.log(getAverage(moreComplexObjects, complexKeyExtractor)); 

A note for the above, if you don't supply a second parameter to Array#reduce , then the first time it runs total will be the first element of the array, however the second time and onwards, it will be the sum so far. 对于上面的注释,如果你没有为Array#reduce提供第二个参数,那么它一次运行total将是数组的第一个元素,但是第二次及以后,它将是到目前为止的总和。 It's not worth handling that case, so supplying an initial value solves it. 处理这种情况并不值得,因此提供初始值可以解决这个问题。

We can use Array.reduce to compute the sum, where acc is the accumulated sum and the individual objects are destructured to the age variable then calculate the average by dividing the sum with the array length: 我们可以使用Array.reduce来计算总和,其中acc是累积的总和,并且各个对象被解构为age变量,然后通过将总和除以数组长度来计算平均值:

 var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ]; function getAvg(arr){ return (people.reduce((acc, {age}) => (acc + age), 0))/arr.length; } console.log(getAvg(people)); 

We can also map the function to the age property and calculate the sum by joining the array into a string and evaluating it inside the Function constructor: 我们还可以将函数映射到age属性,并通过将数组连接到字符串并在Function构造Function对其进行求值来计算总和:

 var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ]; function getAvg(arr){ return (new Function(`return ${people.map(({age}) => age).join("+")}`)()) / arr.length; } console.log(getAvg(people)); 

You could supply a function for the wanted property and reduce with a start value. 您可以为所需属性提供函数,并使用起始值减少。

 const getAverage = (array, fn = v => v) => { var reducer = fn => (total, item) => total + fn(item), sum = array.reduce(reducer(fn), 0); return sum / array.length; }; var people = [{ name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }]; console.log(getAverage(people, o => o.age)); 

More Simplified code 更简化的代码

just execute as getAverage(people.map(p=> p.age)); 只需执行getAverage(people.map(p => p.age)); using your code 使用你的代码

 var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ]; let getAverage = arr => { let reducer = (total, currentValue) => total + currentValue; let sum = arr.reduce(reducer) return sum / arr.length; }; console.log(getAverage(people.map(p=> p.age))); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM