95

I've been looking and haven't found a simple question and answer on stack overflow looking into finding the average of an array.

This is the array that I have

const grades = [80, 77, 88, 95, 68];

I first thought that the answer to this problem would be something like this:

let avg = (grades / grades.length) * grades.length
console.log(avg)

However, this gave me an output of NaN.

So then I tried this:

for (let grade of grades)
    avg = (grade / grades.length) * grades.length
console.log(avg)

This gave me an output of 68. (I'm not sure why).

So with this I have two questions. 1. Why was my output 68? and 2. Could somebody help me out with actually finding the average of an array?

undefined
  • 1,019
  • 12
  • 24
kdweber89
  • 1,984
  • 2
  • 19
  • 29

9 Answers9

153

With ES6 you can turn Andy's solution into as a one-liner:

const average = array => array.reduce((a, b) => a + b) / array.length;
console.log(average([1,2,3,4,5]));
KetZoomer
  • 2,701
  • 3
  • 15
  • 43
Austin
  • 6,241
  • 5
  • 17
  • 12
  • 4
    `(array) =>` part is not needed – TheTechGuy May 06 '21 at 20:07
  • The `(array) =>` part was needed for this to work for me! – Caleb Jun 10 '21 at 23:11
  • 2
    `(array)=>` is needed if you want to make this a standalone function; without it is a value (that assumes you have an existing `array` value and is called using `average` instead of `average(...)`. – Nixinova Jun 24 '21 at 08:22
  • Would someone mind explaining more about how this works? – John-Henry Sep 22 '21 at 17:49
  • I can't explain it because it goes into how javascript syntax works etc and that's hard to explain... but I can rewrite it more clear for you so maybe you can understand what's it doing `myArray = [1,2,3,4]; myArray.reduce((total, current) => total + current) / myArray.length ` The key here is that the `reduce` function will iterate through `myArray` and sum up the values and store it in `total` and then return `total`. – vinhboy Oct 29 '21 at 20:58
  • Slight improvement: https://stackoverflow.com/a/72565782/75129 – zumalifeguard Jun 09 '22 at 19:40
72

You calculate an average by adding all the elements and then dividing by the number of elements.

var total = 0;
for(var i = 0; i < grades.length; i++) {
    total += grades[i];
}
var avg = total / grades.length;

The reason you got 68 as your result is because in your loop, you keep overwriting your average, so the final value will be the result of your last calculation. And your division and multiplication by grades.length cancel each other out.

bwroga
  • 5,379
  • 2
  • 23
  • 25
  • I'd like to point out a gotcha in JavaScript. if you define the variable total to undefined you will get NaN. ```let total; let grades = [90, 30, 40, 50, 60]; for (let i = 0; i < grades.length; i++) { total += grades[i]; } let avg = total / grades.length; console.log(avg) ``` – pixel 67 Aug 23 '19 at 08:41
  • my `code` isn't being formatted? – pixel 67 Aug 23 '19 at 08:44
  • Some people have suggested edits to this post to make the code more concise/nicer. It was my intention not to provide the best way of finding the average of an array in javascript, but to stick as closely to the op's code to point out what they did wrong. – bwroga Jul 16 '21 at 18:32
38

For the second part of your question you can use reduce to good effect here:

const grades = [80, 77, 88, 95, 68];

function getAvg(grades) {
  const total = grades.reduce((acc, c) => acc + c, 0);
  return total / grades.length;
}

const average = getAvg(grades);
console.log(average);

The other answers have given good insight into why you got 68, so I won't repeat it here.

Andy
  • 61,948
  • 13
  • 68
  • 95
  • May I suggest ES7 syntax: `const getAvg = grades => grades.reduce((p,c) => p+c) / grades.length` – TOPKAT Apr 12 '19 at 20:00
  • 7
    If you're going to use `reduce` then you should use the full capabilities of it. `array.reduce((all, one, _, src) => all += one / src.length, 0)` – Braains Jul 09 '19 at 17:53
22

The MacGyver way, just for lulz

var a = [80, 77, 88, 95, 68];

console.log(eval(a.join('+'))/a.length)
Pikamander2
  • 7,332
  • 3
  • 48
  • 69
Mihai
  • 26,325
  • 7
  • 66
  • 81
  • 5
    While funny, I believe someone might use it or say 'oh! this eval function looks very powerful!', so I'll still downvote :) – Adam Pietrasiak May 22 '18 at 07:49
  • 6
    Why is this a bad use of eval? No security issue apparent => upvote. – Daniel W. Apr 12 '19 at 12:46
  • 4
    @DanielW. Because eval is always frowned upon as developers with basic experience may simply see eval and start using it everywhere – which is, of course, a risk. It's just generally regarded as bad practice. – alistair Apr 18 '20 at 09:24
  • 1
    @DanielW. It's a bad use because if the program did not carefully check the array input, someone could insert a string and easily execute arbitrary code. Try: `var a = ["alert('Some evil code.')", 77, 88, 95, 68]; console.log(eval(a.join('+'))/a.length);`. – Ben Zelnick Jan 10 '23 at 00:08
10

It can simply be done with a single reduce operation as follows;

var avg = [1,2,3,4].reduce((p,c,_,a) => p + c/a.length,0);
console.log(avg)
Redu
  • 25,060
  • 6
  • 56
  • 76
  • 2
    Like Vlad's answer, this approach gives rounding errors. If you try to average `[1,1,1,1,1,1]`, you won't get 1. – antun Jun 28 '20 at 00:48
  • 1
    This is the only solution that correctly handles the case where the array is empty, other answers will result in `NaN` due to a divide by 0 error – Niles Tanner Oct 18 '21 at 19:42
9

There's no built in function, but you can use this to get the sum,

Array.prototype.sum = function() {
    return this.reduce(function(a, b) {return a+b});
};

then divide by the array's length, e.g.:

var arr = [1, 2, 3, 4, 5];
console.log(arr.sum() / arr.length)
Community
  • 1
  • 1
baao
  • 71,625
  • 17
  • 143
  • 203
5
var total = 0
grades.forEach(function (grade) {
    total += grade        
});
console.log(total / grades.length)
Tyler Kelley
  • 167
  • 7
5

The average function you can do is:

const getAverage = (arr) => arr.reduce((p, c) => p + c, 0) / arr.length

Also, I suggest that use the popoular open source tool, eg. Lodash:

const _ = require('lodash')
const getAverage = (arr) => _.chain(arr)
 .sum()
 .divide(arr.length)
 .round(1)
 .value()
Winters Huang
  • 761
  • 10
  • 18
  • 1
    Lodash is great... but if you're going to use lodash, use lodash: `_.mean([4, 2, 8, 6]);` (see also: `_.meanBy` https://lodash.com/docs/4.17.15#meanBy) – Marshall Apr 27 '22 at 16:32
1

You can use map/reduce functions of javascript to find average. Reduce will sum them up, and map will find average.

var avg = grades.map((c, i, arr) => c / arr.length).reduce((p, c) => c + p);
Vlad Bezden
  • 83,883
  • 25
  • 248
  • 179
  • Unfortunately this approach creates rounding errors. e.g. `[ 1, 1, 1, 1, 1, 1 ].map((c, i, arr) => c / arr.length).reduce((p, c) => c + p)` will give a value of `0.9999999999999999`, instead of 1. – antun Jun 28 '20 at 00:46