# How do I make this average function better/more elegant?

I have this function that calculates average. I don't want it to look like this. I am hoping for a less cliche average function. Because I see that most people's look like this. Can anyone help?

``````function mean(array) {
var num=0;
for (var i=1;i<=array.length;i++) num=num+array[i];
var divide=num/array.length;
}​
``````

Can anyone change this up to be better than before? It doesn't have to be more efficient but just look better. Thanks! (By the way I'm new to JavaScript so if you can explain your code that'd be great).

-

First of all, your code is incorrect. Arrays have a starting index of `0`, not `1`. Furthermore, `array.length` is one more than the last filled index (because the length is 1 based, and the array is 0 based. Yes, this is confusing.) So you're starting by not including the first item, and then also adding up an undefined item.

And what happens if you get an empty array? You divide by zero, which is MADNESS!! MADNESS I TELL YOU!

Second, there's a reason the code looks the same as everywhere: You have followed the definition of the average; the sum of components divided by the number of components. There's no shame in this, you should actually be proud that you've managed to conform to the standard.

If you really want, you can make the loop implicit. ES5 (ECMAScript 5, the latest js standard) defined an `Array.prototype.reduce` function (click link for the reference.) It's a perfect fit for your needs, but doesn't change the core algorithm.

Third, your `mean` function is doing something unexpected: Instead of just calculating the mean, it displays it as well. This does not follow expectations (or at least my expectation), as a function which calculates the mean should do that, and just that. That translates to a very important design aspect, which says that a function should do one thing, one thing only, and do it well. Because imagine if `Math.sqrt`, for instance, starts displaying the square roots instead of giving you them. Like division by zero, it's madness all over again!

-
Example code would probably be nice. –  Inkbug Jul 29 '12 at 12:20
@Inkbug Since the OP is new to js, imo it'd be better to let him try first before giving him an already baked solution –  Zirak Jul 29 '12 at 16:33
+1 for "a function which calculates the mean should do that, and just that". –  jmoreno Jul 30 '12 at 2:57
+1 Good answer! I added some sample code for the OP, with a small exercise. –  Joseph Silber Jul 30 '12 at 2:58

Zirak's answer is all the advice you need, but since he didn't actually write any code, here's how I might re-write it.

``````function mean(arr) { // it's ok to use short variable names in short, simple functions
// set all variables at the top, because of variable hoisting
var i,
sum = 0, // try to use informative names, not "num"
len = arr.length; // cache arr.length because accessing it is usually expensive
for (i = 0; i < len; i++) { // arrays start at 0 and go to array.length - 1
sum += arr[i]; // short for "sum = sum + arr[i];"
} // always use brackets. It'll save you headaches in the long run
// don't mash your computation and presentation together; return the result.
return sum / len;
}
``````

Note that this code is optimized for arrays with at least 1 element; if the majority of its uses are on 0-length arrays, you'd see a performance boost if you added a short return.

Alternatively you can use Array.prototype.reduce. I highly recommend that you not use this method - while it is more "unique", it is also much harder to understand and much less efficient. And good code strives to be readable and efficient (and robust), not unique.

``````var mean = (function () { // Use an IIFE to get private storage
// cache this function - it's very expensive to re-create it every time you call mean()
return prev + current;
}
// return an anonymous function. When we call mean(), this is what is called. The reason
// we can't set it directly is because we need something with access to addLast, and we
// don't want addLast in the global scope.
return function (arr) {
};
})(); // end of IIFE. executes the function and sets mean to the return value.
``````
-
+1, but I would do `sum += +arr[i]` to coerce a number out of the item. I also see no problem with returning `NaN` for an empty list - the mean of an empty list is actually not 0. :) –  ANeves Jul 30 '12 at 10:30
@ANeves - `n / 0` is `Infinity`, not `NaN` –  Joseph Silber Jul 30 '12 at 14:11
@ANeves whether to coerce a number is certainly an important consideration, but my preference is to provide documentation and assume the caller reads it. Passing in something other than numbers is a caller error, and it's a bad idea to correct for some errors (`['1', '2', '3']`) but not all (`['thing']`). (actually, I don't think this function should be correcting any user errors, but we don't need to get into that). Also, it bothers me to take a (slight) performance hit in correct-use cases for the sake of code that doesn't even use the function correctly. –  st-boost Jul 30 '12 at 17:42
Well the mean of `[]` is neither `0` nor `Infinity`. `0` seemed like a convenient default to me, but I guess it would be more informative to return `NaN`. Any thoughts? If there's some consensus then I'll edit the code, if necessary. –  st-boost Jul 30 '12 at 17:54
@JosephSilber but it won't divide by 0, it divides by 1. So for an empty array, it returns 0/1 = 0. (0/N = NaN; N/0 = Infinity. 0/0 seems to be NaN too.) –  ANeves Jul 31 '12 at 8:05

More efficient: No; More readable: Yes

``````function mean( list, more ) {

if ( more ) {

list = [].slice.call( arguments );

} else if ( !list || list[0] === undefined ) return;

var a = list,
b = list.length;

return (function execute() {

if ( !a.length ) return 0;

return ( a.pop() / b ) + execute();

})();

}
``````

What this function basically does is use recursion to divide each number in the array by the length of the array. Since this is true...

I use that logic in the function and it works just fine.

-
Though this is a nifty implementation, I feel that it would be a bad choice to ever actually put it in production code. Just my 2 cents though, I suppose. –  Corbin Jul 29 '12 at 7:39
I know; that's why I mentioned it was less efficient. For loops are very fast so it's better to use (well, an improved version) of the OP's function than mine. But if he's looking for a different/readable way to write this, I think the above is the best way. –  David Jul 29 '12 at 12:11
Your definition of elegant is obviously not the same as mine. –  luiscubal Jul 29 '12 at 14:09
@David I think this is significantly less readable than a simple loop (and I suspect a large majority would agree). Fancy code is not always better code, especially when the fancy code is implementing a slower algorithm. –  Corbin Jul 30 '12 at 0:43
Additionally to what has been said, I find this far less readable than the question's code. :( I also frown upon re-declaring the function `execute` on every call. –  ANeves Jul 30 '12 at 10:26