280

I am having problems adding all the elements of an array as well as averaging them out. How would I do this and implement it with the code I currently have? The elements are supposed to be defined as I have it below.

<script type="text/javascript">
//<![CDATA[

var i;
var elmt = new Array();

elmt[0] = "0";
elmt[1] = "1";
elmt[2] = "2";
elmt[3] = "3";
elmt[4] = "4";
elmt[5] = "7";
elmt[6] = "8";
elmt[7] = "9";
elmt[8] = "10";
elmt[9] = "11";

// Problem here
for (i = 9; i < 10; i++){
  document.write("The sum of all the elements is: " + /* Problem here */ + " The average of all the elements is: " + /* Problem here */ + "<br/>");
}   

//]]>
</script>
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
jonathan miller
  • 2,919
  • 2
  • 14
  • 6

35 Answers35

661

A solution I consider more elegant:

const sum = times.reduce((a, b) => a + b, 0);
const avg = (sum / times.length) || 0;

console.log(`The sum is: ${sum}. The average is: ${avg}.`);
Sergi Mansilla
  • 12,495
  • 10
  • 39
  • 48
  • 1
    A try to use this solution here (r3), http://jsfiddle.net/6C3pa/ But the reduce returns a NaN (!)... Oh yeah (!), now I see that is **not "only a+b"** but *"previows+current"*! http://jsfiddle.net/cXRrR/ ... So I need CAUTION and use "previous_result+obj.property" – Peter Krauss Jul 19 '14 at 08:30
  • 26
    with a cumulative moving average, you could do this all within the reduce function (no need for the `sum/times.length` step): `var avg = times.reduce(function(p,c,i){return p+(c-p)/(i+1)},0);` – zamnuts Aug 09 '14 at 08:45
  • Indeed, this is the correct answer. Why loop when you have reduce? – wordsforthewise Jun 16 '15 at 13:45
  • 6
    @zamnuts I'm with you, I think Thor84no comment's totally out of order - I'd be happy to be fired from a place which finds array.reduce too complex. However I wouldn't use your code either, for the simple fact it has a division and two extra additions at ever step, which is never going to be as efficient as a single division at the end – gotofritz Apr 01 '16 at 14:58
  • 19
    In ES2015 it's quite a bit more elegant. `times.reduce((a,b) => (a+b)) / times.length;` – Ray Foss Sep 29 '16 at 16:27
  • 1
    @furf It should be noted that compilers that know what are they doing can make the reduce version even faster than the loop one. At the date of writing this comment, in Firefox the reduce version seems to be faster, so it's a matter of time that other compilers pick up. – dmcontador Jun 02 '17 at 10:19
  • Reduce is present on ECMA5 (ECMA-262, 5th Edition), If your javascript version does not contain the reduce, you can create the method as shown here: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Polyfill – Gabriel Simas Jun 29 '17 at 14:33
  • 12
    @furf 5 years later, it looks like in many modern browsers, the more elegant "reduce()" is faster (or as fast). In Chrome 65 and most firefox reduce is better on that test. – Sir Robert Mar 27 '18 at 14:43
  • Works for me perfectly with the addition of parseFloat(): https://stackoverflow.com/a/66725764/8565438 – zabop Mar 20 '21 at 19:43
  • same as this answer, but compressed: `avg=arr.reduce((a,b)=>a+b,0)/arr.length||0;` – ashleedawg Jan 27 '22 at 00:29
170

ES6

const average = arr => arr.reduce( ( p, c ) => p + c, 0 ) / arr.length;
    
const result = average( [ 4, 4, 5, 6, 6 ] ); // 5
    
console.log(result);
Community
  • 1
  • 1
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
  • 4
    Improved: `Array.prototype.average = function () { var sum = 0, j = 0; for (var i = 0; i < this.length, isFinite(this[i]); i++) { sum += parseFloat(this[i]); ++j; } return j ? sum / j : 0; };` – Gilad Peleg Oct 07 '13 at 12:52
  • 61
    Please, don't extend objects that aren't created by your code. – Brad Nov 06 '13 at 01:08
  • 1
    UPDATE doesnt work for: ["RER","4","3re",5,new Object()].average(); returns 0 instead of expected 4.5 – Luckylooke Mar 06 '14 at 14:57
  • @Luckylooke the reason it does not work is ```isFinite(this[i])``` breaks the loop at the first mismatch, instead of filtering... – mido Jan 15 '15 at 05:31
  • 7
    And this will epically crash when there is no length – Jimmy Kane Jun 22 '17 at 11:26
  • 3
    @JimmyKane No, it will return `NaN`. – bzeaman Nov 30 '17 at 14:49
  • @JimmyKane: FYI `NaN` is not a crash, and it makes sense. If you want to handle it you can check about the size of array before using average. `function myConsumer(arr) { const result = !arr.length ? 0 : average(arr); }` – Abdennour TOUMI Dec 01 '17 at 00:33
  • @AbdennourTOUMI Why would I want to that since there are other solutions that default to 0? In functional programming, you want to avoid guard functions. I get your point it's not my style though. – Jimmy Kane Dec 01 '17 at 10:21
159
var sum = 0;
for( var i = 0; i < elmt.length; i++ ){
    sum += parseInt( elmt[i], 10 ); //don't forget to add the base
}

var avg = sum/elmt.length;

document.write( "The sum of all the elements is: " + sum + " The average is: " + avg );

Just iterate through the array, since your values are strings, they have to be converted to an integer first. And average is just the sum of values divided by the number of values.

Manolis
  • 167
  • 1
  • 12
Marcus Recck
  • 5,075
  • 2
  • 16
  • 26
  • 14
    The only improvement I'd do would be to replace `for(var i = 0; i < elmt.length; i++;)` with `for(var i = 0, l = elmt.length; i < l; i++)` – Dan D. Apr 28 '12 at 01:56
  • i tried this and whenever i try to open the page all that comes up is a blank screen. – jonathan miller Apr 28 '12 at 02:11
  • 5
    not to be that guy or to be off topic but it's a good practice to include the radix argument in parseInt(). By that I mean `sum += parseInt(elmt[i], 10);` assuming elmt[i] is of the base 10. [link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt) – Ryder Brooks Apr 01 '14 at 18:27
  • 9
    Watch out for divisions by 0 (elmt.length might me 0) – caulitomaz Jan 11 '15 at 20:42
  • @DanD. Could you explain why? I guess because in your improvement you don't have to calculate the length of `elmt` each iteration. But is that true? The variable declaration is inside the condition, so isn't `l` set to `elmt.length` each iteration, again and again? – Bram Vanroy Dec 16 '15 at 15:58
  • 2
    @BramVanroy Short story: No, it does not set 'l' every single time. Long story: DanD's solution is to improve the performance/speed, because checking the length of an array every single iteration is slower than actually storing the length in a local variable and referencing it each iteration. – CatalinBerta Dec 31 '15 at 17:22
  • Just a very very little improvement to @DanD. 's comment: using `++i` instead of `i++` should be slightly faster (see [this comment](http://stackoverflow.com/questions/6867876/javascript-i-vs-i#comment21156397_6867907) on another answer). So I would replace the first line of the `for` loop with: `for(var i = 0, l = elmt.length; i < l; ++i)` – Vito Gentile Apr 15 '16 at 10:20
  • 9
    @VitoGentile and DanD uglifying the code for performance gains which modern Browsers compile away anyway should not be best practice. – nauti Aug 10 '16 at 12:00
  • 1
    Use `Number(elmt[i])` instead of `parseInt(elmt[i], 10)`; that’s way cleaner and works for floats, too. – Sebastian Simon Aug 14 '19 at 10:02
51

Calculating average (mean) using reduce and ES6:

const average = list => list.reduce((prev, curr) => prev + curr) / list.length;

const list = [0, 10, 20, 30]
average(list) // 15
ColineDoe
  • 109
  • 1
  • 8
Tomasz Mularczyk
  • 34,501
  • 19
  • 112
  • 166
  • 1
    very very slow compared to a simple for loop based addition with a sum variable http://jsben.ch/0xUus – PirateApp Mar 12 '19 at 13:26
  • Here it's a difference of 25%. Not so bad, I think. – Michael Oct 29 '19 at 14:08
  • Not sure why the benchmark uses an object with numeric keys instead of an array. Here is the same benchmark using an actual array https://jsben.ch/SGU2d . For me (Chrome 103 - Linux) reduce is actually the fastest – Kevin Peña May 31 '22 at 18:58
37

Shortest one liner for Average

const avg = arr => arr.reduce((acc,v,i,a)=>(acc+v/a.length),0);

Shortest one liner for Sum

const sum = arr => arr.reduce((a,b)=>a+b);
chickens
  • 19,976
  • 6
  • 58
  • 55
  • 2
    if you switch the return value to `a+(v-a)/(i+1)` you keep the same number of characters and make it a little more numerically stable, especially relative to all of the answers that divide by `array.length` – Erik Dec 18 '20 at 04:14
24

Let's imagine we have an array of integers like this:

var values = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];

The average is obtained with the following formula

A= (1/n)Σxi ( with i = 1 to n ) ... So: x1/n + x2/n + ... + xn/n

We divide the current value by the number of values and add the previous result to the returned value.

The reduce method signature is

reduce(callback[,default_previous_value])

The reduce callback function takes the following parameters:

  • p : Result of the previous calculation
  • c : Current value (from the current index)
  • i : Current array element's index value
  • a : The current reduced Array

The second reduce's parameter is the default value ... (Used in case the array is empty ).

So the average reduce method will be:

var avg = values.reduce(function(p,c,i,a){return p + (c/a.length)},0);

If you prefer you can create a separate function

function average(p,c,i,a){return p + (c/a.length)};
function sum(p,c){return p + c)};

And then simply refer to the callback method signature

var avg = values.reduce(average,0);
var sum= values.reduce(sum,0);

Or Augment the Array prototype directly..

Array.prototype.sum = Array.prototype.sum || function (){
  return this.reduce(function(p,c){return p+c},0);
};

It's possible to divide the value each time the reduce method is called..

Array.prototype.avg = Array.prototype.avg || function () {
  return this.reduce(function(p,c,i,a){return p+(c/a.length)},0);
};

Or even better , using the previously defined Array.protoype.sum()

method, optimize the process my calling the division only once :)

Array.prototype.avg = Array.prototype.avg || function () {
  return this.sum()/this.length; 
};

Then on any Array object of the scope:

[2, 6].avg();// -> 4
[2, 6].sum();// -> 8

NB: an empty array with return a NaN wish is more correct than 0 in my point of view and can be useful in specific use cases.

mpolci
  • 2,999
  • 1
  • 23
  • 16
Ludovic Frérot
  • 605
  • 4
  • 9
22

generally average using one-liner reduce is like this

elements.reduce(function(sum, a,i,ar) { sum += a;  return i==ar.length-1?(ar.length==0?0:sum/ar.length):sum},0);

specifically to question asked

elements.reduce(function(sum, a,i,ar) { sum += parseFloat(a);  return i==ar.length-1?(ar.length==0?0:sum/ar.length):sum},0);

an efficient version is like

elements.reduce(function(sum, a) { return sum + a },0)/(elements.length||1);

Understand Javascript Array Reduce in 1 Minute http://www.airpair.com/javascript/javascript-array-reduce

as gotofritz pointed out seems Array.reduce skips undefined values. so here is a fix:

(function average(arr){var finalstate=arr.reduce(function(state,a) { state.sum+=a;state.count+=1; return state },{sum:0,count:0}); return finalstate.sum/finalstate.count})([2,,,6])
Shimon Doodkin
  • 4,310
  • 34
  • 37
  • 2
    `elements.length!=0?elements.length:1` can also be written like this : `elements.length || 1` which is shorter, and easier to read. – 4rzael Oct 28 '15 at 11:30
  • 2
    Bear in mind this only works for arrays with no empty gaps – gotofritz Apr 01 '16 at 15:03
  • 2
    Suggestion: Add unminified (actually just pretty-printed) versions of your code snippets so people can read them. I'd edit them in myself, but I don't like to change people's answers to that extent. – Justin Morgan - On strike Apr 11 '17 at 15:50
21

You can also use lodash, _.sum(array) and _.mean(array) in Math part (also have other convenient stuff).

_.sum([4, 2, 8, 6]);
// => 20
_.mean([4, 2, 8, 6]);
// => 5
WoJ
  • 27,165
  • 48
  • 180
  • 345
Geng Jiawen
  • 8,904
  • 3
  • 48
  • 37
6

Not the fastest, but the shortest and in one line is using map() & reduce():

var average = [7,14,21].map(function(x,i,arr){return x/arr.length}).reduce(function(a,b){return a + b})
Johann Echavarria
  • 9,695
  • 4
  • 26
  • 32
  • 1
    maybe shorter `[7,14,21].reduce((avg,e,i,arr)=>avg+e/arr.length,0);` but with different behaviour on empty array. If you do want the outcome to be empty on empty array: `[].reduce((a,e,i,arr)=>(a?a:0)+e/arr.length,"")` – Valen Jun 03 '17 at 11:53
  • @Tobiq map & reduce are pretty standard since ES5 (standardized in 2009) – Johann Echavarria Sep 19 '17 at 15:44
  • `for (var avg = 0, length = i = arr.length; i--;) avg += arr[i] / length` Much clearer, shorter and much faster – Tobiq Sep 19 '17 at 17:15
  • 2
    @Tobiq, your code is anything but clear. This type of loop is unintelligible at first glance. – Porkopek May 01 '18 at 10:19
6

I use these methods in my personal library:

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

Array.prototype.average = Array.prototype.average || function() {
  return this.sum() / (this.length || 1);
}

EDIT: To use them, simply ask the array for its sum or average, like:

[1,2,3].sum() // = 6
[1,2,3].average() // = 2
Keith
  • 984
  • 6
  • 9
  • Neat implementation althought I would have implemented sum to use a for loop instead of reduce. Still very cleanly coded though. – XDS Aug 23 '16 at 09:46
6

In ES6-ready browsers this polyfill may be helpful.

Math.sum = (...a) => Array.prototype.reduce.call(a,(a,b) => a+b)

Math.avg = (...a) => Math.sum(...a)/a.length;

You can share same call method between Math.sum,Math.avg and Math.max,such as

var maxOne = Math.max(1,2,3,4) // 4;

you can use Math.sum as

var sumNum = Math.sum(1,2,3,4) // 10

or if you have an array to sum up,you can use

var sumNum = Math.sum.apply(null,[1,2,3,4]) // 10

just like

var maxOne = Math.max.apply(null,[1,2,3,4]) // 4
Oboo Cheng
  • 4,250
  • 3
  • 24
  • 29
  • Instead of adding methods to `Array.prototype`,I think adding theme to `Math` object is a better choice - they are all "number handlers". – Oboo Cheng Nov 18 '16 at 15:59
  • You can't use the "this" like that in an arrow function. It will thow "TypeError: this.sum is not a function" because the "this" will refer to the context from which the arrow function is called, which is window in this case. Change it to "Math.sum(...)". – FireFuro99 Sep 04 '22 at 04:50
  • 1
    @FireFuro99 ur right, have no idea why leave this for such a long time, updated – Oboo Cheng Sep 05 '22 at 14:49
4

One sneaky way you could do it although it does require the use of (the much hated) eval().

var sum = eval(elmt.join('+')), avg = sum / elmt.length;
document.write("The sum of all the elements is: " + sum + " The average of all the elements is: " + avg + "<br/>");

Just thought I'd post this as one of those 'outside the box' options. You never know, the slyness might grant you (or taketh away) a point.

Phil Cooper
  • 3,083
  • 39
  • 63
  • +1 Nice efficient one-liner! If it's client-side in-browser Javascript, the only possible `eval()` issue I can see is that you need to be sure the array contains numbers only (which of course is also true for all other answers here). Non-numeric entries crash with a `ReferenceError` or `SyntaxError, except nested arrays of numbers which introduce `,` causing an incorrect numeric total. And of course in server side JS, e.g. node.js, then naturally `eval()` might introduce security issues. But this looks perfect for any well-structured client-side uses. – user56reinstatemonica8 Dec 03 '13 at 13:08
  • 1
    Actually there's maybe a performance issue to including `eval()` like this - see the performance section of http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/ – user56reinstatemonica8 Dec 04 '13 at 11:57
  • OMG! eval. OMG! OMG! OMG! - It answers the question succinctly and is different from the other answers. There are cases where `eval()` is the only way to solve a problem. This, um, isn't one of them. – Stephen Quan Aug 22 '22 at 06:09
4

Here is a quick addition to the “Math” object in javascript to add a “average” command to it!!

Math.average = function(input) {
  this.output = 0;
  for (this.i = 0; this.i < input.length; this.i++) {
    this.output+=Number(input[this.i]);
  }
  return this.output/input.length;
}

Then i have this addition to the “Math” object for getting the sum!

Math.sum = function(input) {
  this.output = 0;
  for (this.i = 0; this.i < input.length; this.i++) {
    this.output+=Number(input[this.i]);
  }
  return this.output;
}

So then all you do is

alert(Math.sum([5,5,5])); //alerts “15”
alert(Math.average([10,0,5])); //alerts “5”

And where i put the placeholder array just pass in your variable (The input if they are numbers can be a string because of it parsing to a number!)

Jacob Morris
  • 544
  • 4
  • 18
4

I found Mansilla's answer to work fine with the extension of making sure that I am doing summation of floats and not concatonation of strings using parseFloat():

let sum = ourarray.reduce((a, b) => parseFloat(a) + parseFloat(b), 0);
let avg = (sum / ourarray.length) || 0;

console.log(sum); // print out sum
console.log(avg); // print out avg
zabop
  • 6,750
  • 3
  • 39
  • 84
1

set your for loop counter to 0.... you're getting element 9 and then you're done as you have it now. The other answers are basic math. Use a variable to store your sum (need to cast the strings to ints), and divide by your array length.

Volvox
  • 611
  • 2
  • 7
  • 19
1

Start by defining all of the variables we plan on using. You'll note that for the numbers array, I'm using the literal notation of [] as opposed to the constructor method array(). Additionally, I'm using a shorter method to set multiple variables to 0.

var numbers = [], count = sum = avg = 0;

Next I'm populating my empty numbers array with the values 0 through 11. This is to get me to your original starting point. Note how I'm pushing onto the array count++. This pushing the current value of count, and then increments it for the next time around.

while ( count < 12 )
    numbers.push( count++ );

Lastly, I'm performing a function "for each" of the numbers in the numbers array. This function will handle one number at a time, which I'm identifying as "n" within the function body.

numbers.forEach(function(n){
  sum += n; 
  avg = sum / numbers.length;
});

In the end, we can output both the sum value, and the avg value to our console in order to see the result:

// Sum: 66, Avg: 5.5
console.log( 'Sum: ' + sum + ', Avg: ' + avg );

See it in action online at http://jsbin.com/unukoj/3/edit

Sampson
  • 265,109
  • 74
  • 539
  • 565
1

I am just building on Abdennour TOUMI's answer. here are the reasons why:

1.) I agree with Brad, I do not think it is a good idea to extend object that we did not create.

2.) array.length is exactly reliable in javascript, I prefer Array.reduce beacuse a=[1,3];a[1000]=5; , now a.length would return 1001.

function getAverage(arry){
    // check if array
    if(!(Object.prototype.toString.call(arry) === '[object Array]')){
        return 0;
    }
    var sum = 0, count = 0; 
    sum = arry.reduce(function(previousValue, currentValue, index, array) {
        if(isFinite(currentValue)){
            count++;
            return previousValue+ parseFloat(currentValue);
        }
        return previousValue;
    }, sum);
    return count ? sum / count : 0; 
};
mido
  • 24,198
  • 15
  • 92
  • 117
1
Array.prototype.avg=function(fn){
    fn =fn || function(e,i){return e};
    return (this.map(fn).reduce(function(a,b){return parseFloat(a)+parseFloat(b)},0) / this.length ) ; 
};

Then :

[ 1 , 2 , 3].avg() ;  //-> OUT : 2

[{age:25},{age:26},{age:27}].avg(function(e){return e.age}); // OUT : 26
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
1

On evergreen browsers you can use arrow functions avg = [1,2,3].reduce((a,b) => (a+b);

Running it 100,000 times, the time difference between the for loop approach and reduce is negligible.

s=Date.now();for(i=0;i<100000;i++){ n=[1,2,3]; a=n.reduce((a,b) => (a+b)) / n.length };
console.log("100k reduce took " + (Date.now()-s) + "ms.");

s=Date.now();for(i=0;i<100000;i++){n=[1,2,3]; nl=n.length; a=0; for(j=nl-1;j>0;j--){a=a+n[j];} a/nl };
console.log("100k for loop took " + (Date.now()-s) + "ms.");

s=Date.now();for(i=0;i<1000000;i++){n=[1,2,3]; nl=n.length; a=0; for(j=nl-1;j>0;j--){a=a+n[j];} a/nl };
console.log("1M for loop took " + (Date.now()-s) + "ms.");

s=Date.now();for(i=0;i<1000000;i++){ n=[1,2,3]; a=n.reduce((a,b) => (a+b)) / n.length };
console.log("1M reduce took " + (Date.now()-s) + "ms.");

/* 
 * RESULT on Chrome 51
 * 100k reduce took 26ms.
 * 100k for loop took 35ms.
 * 10M for loop took 126ms.
 * 10M reduce took 209ms.
 */
Ray Foss
  • 3,649
  • 3
  • 30
  • 31
  • 2
    You need to learn more about `console.time` & `console.timeEnd` – Abdennour TOUMI Oct 04 '16 at 21:07
  • @AbdennourTOUMI Thanks for the tip, I'll keep it in mind... however it's non standard and not on standards track. https://developer.mozilla.org/en-US/docs/Web/API/Console/timeEnd – Ray Foss Oct 06 '16 at 18:48
  • 1
    I know I'm veering off the original questions but how about using performance.now() for performance measurements? – deejbee Nov 02 '16 at 08:31
  • @deejbee That does offer floating point accuracy... but it's also a tad more verbose and less compatible. Setting markers with it would be useful in real world code – Ray Foss Nov 02 '16 at 12:40
1

If you are in need of the average and can skip the requirement of calculating the sum, you can compute the average with a single call of reduce:

// Assumes an array with only values that can be parsed to a Float
var reducer = function(cumulativeAverage, currentValue, currentIndex) {
  // 1. multiply average by currentIndex to find cumulative sum of previous elements
  // 2. add currentValue to get cumulative sum, including current element
  // 3. divide by total number of elements, including current element (zero-based index + 1)
  return (cumulativeAverage * currentIndex + parseFloat(currentValue))/(currentIndex + 1)
}
console.log([1, 2, 3, 4, 5, 6, 7, 8, 9, 10].reduce(reducer, 0)); // => 5.5
console.log([].reduce(reducer, 0)); // => 0
console.log([0].reduce(reducer, 0)); // => 0
console.log([].reduce(reducer, 0)); // => 0
console.log([,,,].reduce(reducer, 0)); // => 0
console.log([].reduce(reducer, 0)); // => 0
sealocal
  • 10,897
  • 3
  • 37
  • 50
1

If anyone ever needs it - Here is a recursive average.

In the context of the original question, you may want to use the recursive average if you allowed the user to insert additional values and, without incurring the cost of visiting each element again, wanted to "update" the existing average.

/**
 * Computes the recursive average of an indefinite set
 * @param {Iterable<number>} set iterable sequence to average
 * @param {number} initAvg initial average value
 * @param {number} initCount initial average count
 */
function average(set, initAvg, initCount) {
  if (!set || !set[Symbol.iterator])
    throw Error("must pass an iterable sequence");

  let avg = initAvg || 0;
  let avgCnt = initCount || 0;
  for (let x of set) {
    avgCnt += 1;
    avg = avg * ((avgCnt - 1) / avgCnt) + x / avgCnt;
  }
  return avg; // or {avg: avg, count: avgCnt};
}

average([2, 4, 6]);    //returns 4
average([4, 6], 2, 1); //returns 4
average([6], 3, 2);    //returns 4
average({
  *[Symbol.iterator]() {
    yield 2; yield 4; yield 6;
  }
});                    //returns 4

How:

this works by maintaining the current average and element count. When a new value is to be included you increment count by 1, scale the existing average by (count-1) / count, and add newValue / count to the average.

Benefits:

  • you don't sum all the elements, which may result in large number that cannot be stored in a 64-bit float.
  • you can "update" an existing average if additional values become available.
  • you can perform a rolling average without knowing the sequence length.

Downsides:

  • incurs lots more divisions
  • not infinite - limited to Number.MAX_SAFE_INTEGER items unless you employ BigNumber
Meirion Hughes
  • 24,994
  • 12
  • 71
  • 122
1

Having read the other choices, I will try to make a simpler version for the future viewers, elaborating on the existing code and not creating a more elegant one. First of all, you declared the numbers as strings. Apart from the .parseInt we can also do:

const numberConverter = elmt.map(Number);

So what map does is that it "returns a copy of the original array". But I convert its values to numbers. Then we can use the reduce method (It can also be simpler, but I am writing easy to read versions and I also have 2 average methods) What the reduce method does is it has an accumulator that gets bigger and bigger if you add values to it, as it iterates through the array and adds (in this case) the currentValue to it.:

var i;
const elmt = new Array();
elmt[0] = '0';
elmt[1] = '1';
elmt[2] = '2';
elmt[3] = '3';
elmt[4] = '4';
elmt[5] = '7';
elmt[6] = '8';
elmt[7] = '9';
elmt[8] = '10';
elmt[9] = '11';

console.log(elmt);

const numberConverter = elmt.map(Number);

const sum = numberConverter.reduce((accumulator, currentValue) => {
  return accumulator + currentValue;
}, 0);

const average = numberConverter.reduce(
  (accumulator, currentvalue, index, numArray) => {
    return accumulator + currentvalue / numArray.length;
  },
  0
);

const average2 =
  numberConverter.reduce(
    (accumulator, currentValue) => accumulator + currentValue,
    0
  ) / numberConverter.length;

for (i = 9; i < 10; i++) {
  console.log(
    `The sum of all the elements is: ${sum}. <br> The average of all the elements is: ${average2}`
  );}
1

Unless I missed something, every solution up to this point uses the length of the list to calculate the average after summing the values.

There is a downside to this approach that a slightly modified, yet still simple algorithm will address without the downsides.

The downside is that you assuming that there won't be an overflow by summing all the numbers. If you have a lot of numbers that are very big, and you add them all up, they may exceed the maximum size that can fit into the data type.

A better approach is to simply calculate the average as you go, rather than summing it and then dividing with the length at the end:

function getAvg(values) {
    return values.reduce((m, x, i) => m + (x - m) / (i + 1), 0)
}

Props to Knuth's "Art of Computer Programming" vol. 2.

zumalifeguard
  • 8,648
  • 5
  • 43
  • 56
1

just for fun

let avg = [81, 77, -88, 195, 6.8].reduce((a,e,i) => (a*i+e)/(i+1));

console.log(avg)
Nathan Sutherland
  • 1,191
  • 7
  • 9
0

Just for kicks:

var elmt = [0, 1, 2,3, 4, 7, 8, 9, 10, 11], l = elmt.length, i = -1, sum = 0;
for (; ++i < l; sum += elmt[i])
    ;
document.body.appendChild(document.createTextNode('The sum of all the elements is: ' + sum + ' The average of all the elements is: ' + (sum / l)));
0

I think we can do like

var k=elmt.reduce(function(a,b){return parseFloat(a+parseFloat(b));})
var avg=k/elmt.length; 
console.log(avg);

I am using parseFloat twice because when 1) you add (a)9+b("1") number then result will be "91" but we want addition. so i used parseFloat

2)When addition of (a)9+parseFloat("1") happen though result will be "10" but it will be in string which we don't want so again i used parseFloat.

I hope i am clear. Suggestions are welcome

Roli Agrawal
  • 2,356
  • 3
  • 23
  • 28
0

Here is my rookie way of simply finding the avg. Hope this helps somebody.

function numAvg(num){
    var total = 0;
    for(var i = 0;i < num.length; i++) { 
        total+=num[i];
    }
    return total/num.length;
}
Rob
  • 5,353
  • 33
  • 34
Jeremiah
  • 1
  • 1
0

here's your one liner:

var average = arr.reduce((sum,item,index,arr)=>index !== arr.length-1?sum+item:sum+item/arr.length,0)
Alex C.
  • 4,021
  • 4
  • 21
  • 24
0

I think this may be a direct solution to calculate the average with a for loop and function.

var elmts = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];

function average(arr) {
    var total = 0;
    for (var i = 0; i < arr.length; i++) {
        total += arr[i];
    }
        console.log(Math.round(total/arr.length));
}

average(elmts);
Vemonus
  • 868
  • 1
  • 16
  • 28
redcoder
  • 1
  • 1
0

There seem to be an endless number of solutions for this but I found this to be concise and elegant.

const numbers = [1,2,3,4];
const count = numbers.length;
const reducer = (adder, value) => (adder + value);
const average = numbers.map(x => x/count).reduce(reducer);
console.log(average); // 2.5

Or more consisely:

const numbers = [1,2,3,4];
const average = numbers.map(x => x/numbers.length).reduce((adder, value) => (adder + value));
console.log(average); // 2.5

Depending on your browser you may need to do explicit function calls because arrow functions are not supported:

const r = function (adder, value) {
        return adder + value;
};
const m = function (x) {
        return x/count;
};
const average = numbers.map(m).reduce(r);
console.log(average); // 2.5

Or:

const average1 = numbers
    .map(function (x) {
        return x/count;
     })
    .reduce(function (adder, value) {
        return adder + value;
});
console.log(average1);
Charles Owen
  • 2,403
  • 1
  • 14
  • 25
  • You are making N divisions in map function. It is better to first reduce all numbers to a total value and then make only one division – Eugenio May 24 '18 at 13:03
-1

Average of HTML content itens

With jQuery or Javascript's querySelector you have direct acess to formated data... Example:

<p>Elements for an average: <span class="m">2</span>, <span class="m">4</span>,
   <span class="m">2</span>, <span class="m">3</span>.
</p>

So, with jQuery you have

var A = $('.m')
  .map(function(idx) { return  parseInt($(this).html()) })
  .get();
var AVG = A.reduce(function(a,b){return a+b}) / A5.length;

See other more 4 ways (!) to access itens and average it: http://jsfiddle.net/4fLWB/

Community
  • 1
  • 1
Peter Krauss
  • 13,174
  • 24
  • 167
  • 304
  • 2
    Downvote because the OP asked to to do X and you told him how to do Y then X. Also, the idea of pulling data from the DOM rather than creating the DOM from data seems like something you'd probably want to avoid anyways. – eremzeit Jan 07 '16 at 18:08
  • Hi @eremzeit, thanks attention. I use bold title to say "it is other case, with contents into HTML", please considere it... About relevante, this kind of use (direct access of data from HTML that user see) is not an academic game... It is about the "auditable truth", that is into HTML (!), not "hidden from humans" at javascript... Not only at Wikipedia, see typical cases: [3.7 million scientific articles at PMC](http://www.ncbi.nlm.nih.gov/pmc/), [6.6 MILLION of legislative documents at LexML](http://www.lexml.gov.br/). Some people not do only design and games with js, do tools for audit. – Peter Krauss Jan 07 '16 at 18:37
-1

var arr = [1,2,3,4,5]

function avg(arr){
  var sum = 0;
  for (var i = 0; i < arr.length; i++) {
    sum += parseFloat(arr[i])
  }
  return sum / i;
}

avg(arr) ======>>>> 3

This works with strings as numbers or numbers in the array.

dan chow
  • 59
  • 2
  • 8
-2
    var scores =[90, 98, 89, 100, 100, 86, 94];
        var sum = 0;
        var avg = 0;
        for(var i = 0; i < scores.length;i++){
  //Taking sum of all the arraylist
            sum = sum + scores[i];   
                }
  //Taking average     
             avg = sum/scores.length;        
  //this is the function to round a decimal no    
             var round = avg.toFixed();
             console.log(round);
  • 1
    Welcome to Stack Overflow. Your answer should explain in detail why and how it answers the question. While code snippets are encouraged you should explain the code so that visitors can understand it. There is a how to answer guide here: https://stackoverflow.com/help/how-to-answer – ChrisM Mar 20 '19 at 17:54
-3

I would recommend D3 in this case. It is the most readable (and provides 2 different kinds of averages)

let d3 = require('d3');
let array = [1,2,3,4];
let sum = d3.sum(array); //10
let mean = d3.mean(array); //2.5
let median = d3.median(array); 
Code Whisperer
  • 22,959
  • 20
  • 67
  • 85
-3

I had exactly 10 elements (like in the example) so I did:

( elmt[0] + elmt[1] + elmt[2] + elmt[3] + elmt[4] +
  elmt[5] + elmt[6] + elmt[7] + elmt[8] + elmt[9] ) / 10
user40521
  • 1,997
  • 20
  • 8