views:

111

answers:

3

Say I have an array-ish container of decimal numbers. I want the sum. In Python I would do this:

x = [1.2, 3.4, 5.6]

sum(x)

Is there a similarly concise way to do this in JavaScript?

+7  A: 

I guess there's none... but you can make one on javascript

Array.prototype.sum = function() {
  return (! this.length) ? 0 : this.slice(1).sum() +
      ((typeof this[0] == 'number') ? this[0] : 0);
};

use it as,

[1,2,3,4,5].sum() //--> returns 15
[1,2,'',3,''].sum() //--> returns 6
[].sum() //--> returns 0    
x = [1.2, 3.4, 5.6]
x.sum(); // returns 10.2

demo


Okay as pointed out in the comment, you can also do it as non-recursive way

Array.prototype.sum = function() {
   var num = 0;
   for (var i = 0; i < this.length; i++) {
       num += (typeof this[i] == 'number') ? this[i] : 0;
   }
   return num;
};

Another way to do it, through function..

function sum(arr) {
   var num = 0;
   for (var i = 0; i < arr.length; i++) {
       num += (typeof arr[i] == 'number') ? arr[i] : 0;
   }
   return num;
};

use it as,

sum([1,2,3,4,5]) //--> returns 15
x = [1.2, 3.4, 5.6]
sum(x); // returns 10.2
Reigel
just out of curiosity, wouldn't this recursive implementation easily hit the stack limit? Any reason not to use an iterative solution with a for loop?
catchmeifyoutry
This is a terrible solution. Please do not go modifying object prototypes. I've run into serious issues with this kind of nonsense. Write a $.sum jQuery plugin, and don't screw the rest of us.
Stefan Kendall
@Stefan Kendall can you give me something to read or any for that matter? `modifying object prototypes`... ;)
Reigel
@Stefan, wish I could +1000 you -- the ability to modify built-ins is one detail I classify as a defect in JS (and Ruby) and it has never given me anything but trouble (esp. in JS as I don't use Ruby much;-).
Alex Martelli
@Reigel: Give a look to [this article](http://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/).
CMS
@CMS, thanks for the link... @Stefan, could you do the honor to edit my function above as `$.sum`?
Reigel
Writing static jQuery plugin methods is literally trivial. Stick `$.sum =` in front of your function, and you have a jQuery plugin :P
Stefan Kendall
@Reigel: You're welcome, BTW the [`slice`](https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/slice) method call on your recursive approach can be *really* expensive, because `slice` will generate a new array object each time is invoked.
CMS
Thanks for your thorough suggestions!
twneale
+8  A: 

Another approach, a simple iterative function:

function sum(arr) {
  var result = 0, n = arr.length || 0; //may use >>> 0 to ensure length is Uint32
  while(n--) {
    result += +arr[n]; // unary operator to ensure ToNumber conversion
  }
  return result;
}

var x = [1.2, 3.4, 5.6];
sum(x); // 10.2

Yet another approach using Array.prototype.reduce:

var arr = [1.2, 3.4, 5.6];
arr.reduce(function (a, b) { return a + b; }, 0); // 10.2

The reduce method is part of the ECMAScript 5th Edition standard, is widely available, but is not on IE <= 8, however an implementation cay be included from the the Mozilla Dev Center I linked.

CMS
+1 for `reduce`.
Ken Redler
I particularly like the use of reduce. Somehow, it isn't very widely used, and I personally feel it deserves more takers. +1
dhruvbird
+1 Wow, really concise.
twneale
A: 

var x = [1.2, 3.4, 5.6], sum=eval(x.join('+'));

alert(sum) // 10.2

Oh, don't forget that eval is evil....

kennebec
The array will almost certainly come from user input.var x = ["alert('You got owned');//",3];
Stefan Kendall