113

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?

0

9 Answers 9

193

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]));

Sign up to request clarification or add additional context in comments.

6 Comments

(array) => part is not needed
The (array) => part was needed for this to work for me!
(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(...).
Would someone mind explaining more about how this works?
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.
|
75

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.

3 Comments

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)
my code isn't being formatted?
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.
44

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

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

function getAvg(grades) {
  if (grades.length === 0) return 'Empty grades array';
  return grades.reduce((acc, c) => acc + c, 0) / grades.length;
}

console.log(getAvg(grades));
console.log(getAvg(grades2));

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

3 Comments

May I suggest ES7 syntax: const getAvg = grades => grades.reduce((p,c) => p+c) / grades.length
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 - as called out by @antun in another answer, this starts to generate rounding errors. For instance, do your code with the array [1,1,1,1,1,1] ... you get 0.9999999999999999. The error worsens with each additional 1 in the array.
21

The MacGyver way, just for lulz

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

console.log(eval(a.join('+'))/a.length)

5 Comments

While funny, I believe someone might use it or say 'oh! this eval function looks very powerful!', so I'll still downvote :)
Why is this a bad use of eval? No security issue apparent => upvote.
@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.
@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);.
It is not recommended to use eval because I am not a number but a function in an object with an alternating toString function, this may have a security hole. before use eval you need verify it contain only number. with someting like if(a.findIndex((i)=>typeof i!='number')!=-1) throw new error('Not a number');
13

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)

2 Comments

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.
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
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)

Comments

5
var total = 0
grades.forEach(function (grade) {
    total += grade        
});
console.log(total / grades.length)

Comments

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()

1 Comment

Lodash is great... but if you're going to use lodash, use lodash: _.mean([4, 2, 8, 6]); (see also: _.meanBy lodash.com/docs/4.17.15#meanBy)
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);

1 Comment

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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.