How to find the sum of an array of numbers

后端 未结 30 2583
醉话见心
醉话见心 2020-11-21 13:36

Given an array [1, 2, 3, 4], how can I find the sum of its elements? (In this case, the sum would be 10.)

I thought $.each might be useful,

相关标签:
30条回答
  • 2020-11-21 14:06
    // Given array 'arr'
    var i = arr.length;
    var sum = 0;
    while (--i) sum += arr[i];
    

    This will take on average 1.57 ms/run (measured over 1000 runs on an array of 100 random normal numbers), compared to 3.604 ms/run with the eval() method above and 2.151 ms/run with a standard for(i,length,++) loop.

    Methodology note: this test was run on a Google Apps Script server, so their javascript engines are pretty much the same as Chrome.

    EDIT: --i instead of i-- saves 0.12 ms each run (i-- is 1.7)

    EDIT: Holy expletive, never mind this whole post. Use the reduce() method mentioned above, it's only 1 ms/run.

    0 讨论(0)
  • 2020-11-21 14:07

    Recommended (reduce with default value)

    Array.prototype.reduce can be used to iterate through the array, adding the current element value to the sum of the previous element values.

    console.log(
      [1, 2, 3, 4].reduce((a, b) => a + b, 0)
    )
    console.log(
      [].reduce((a, b) => a + b, 0)
    )

    Without default value

    You get a TypeError

    console.log(
      [].reduce((a, b) => a + b)
    )

    Prior to ES6's arrow functions

    console.log(
      [1,2,3].reduce(function(acc, val) { return acc + val; }, 0)
    )
    
    console.log(
      [].reduce(function(acc, val) { return acc + val; }, 0)
    )

    Non-number inputs

    If non-numbers are possible inputs, you may want to handle that?

    console.log(
      ["hi", 1, 2, "frog"].reduce((a, b) => a + b)
    )
    
    let numOr0 = n => isNaN(n) ? 0 : n
    
    console.log(
      ["hi", 1, 2, "frog"].reduce((a, b) => 
        numOr0(a) + numOr0(b))
    )

    Non-recommended dangerous eval use

    We can use eval to execute a string representation of JavaScript code. Using the Array.prototype.join function to convert the array to a string, we change [1,2,3] into "1+2+3", which evaluates to 6.

    console.log(
      eval([1,2,3].join('+'))
    )
    
    //This way is dangerous if the array is built
    // from user input as it may be exploited eg: 
    
    eval([1,"2;alert('Malicious code!')"].join('+'))

    Of course displaying an alert isn't the worst thing that could happen. The only reason I have included this is as an answer Ortund's question as I do not think it was clarified.

    0 讨论(0)
  • 2020-11-21 14:10

    This is possible by looping over all items, and adding them on each iteration to a sum-variable.

    var array = [1, 2, 3];
    
    for (var i = 0, sum = 0; i < array.length; sum += array[i++]);
    

    JavaScript doesn't know block scoping, so sum will be accesible:

    console.log(sum); // => 6
    

    The same as above, however annotated and prepared as a simple function:

    function sumArray(array) {
      for (
        var
          index = 0,              // The iterator
          length = array.length,  // Cache the array length
          sum = 0;                // The total amount
          index < length;         // The "for"-loop condition
          sum += array[index++]   // Add number on each iteration
      );
      return sum;
    }
    
    0 讨论(0)
  • 2020-11-21 14:11

    In Lisp, this'd be exactly the job for reduce. You'd see this kind of code:

    (reduce #'+ '(1 2 3)) ; 6
    

    Fortunately, in JavaScript, we also have reduce! Unfortunately, + is an operator, not a function. But we can make it pretty! Here, look:

    const sum = [1, 2, 3].reduce(add,0); // with initial value to avoid when the array is empty
    
    function add(accumulator, a) {
        return accumulator + a;
    }
    
    console.log(sum); // 6
    

    Isn't that pretty? :-)

    Even better! If you're using ECMAScript 2015 (aka ECMAScript 6), it can be this pretty:

    const sum = [1, 2, 3].reduce((partial_sum, a) => partial_sum + a,0); 
    console.log(sum); // 6
    
    0 讨论(0)
  • 2020-11-21 14:11

    Accuracy

    Sort array and start sum form smallest numbers (snippet shows difference with nonsort)

    [...arr].sort((a,b)=>a-b).reduce((a,c)=>a+c,0)
    

    arr=[.6,9,.1,.1,.1,.1]
    
    sum     =                       arr.reduce((a,c)=>a+c,0)
    sortSum = [...arr].sort((a,b)=>a-b).reduce((a,c)=>a+c,0)
    
    console.log('sum:     ',sum);
    console.log('sortSum:',sortSum);
    console.log('sum==sortSum :', sum==sortSum);
    
    // we use .sort((a,b)=>a-b) instead .sort() because
    // that second one treat elements like strings (so in wrong way)
    // e.g [1,10,9,20,93].sort() -->  [1, 10, 20, 9, 93]

    For multidimensional array of numbers use arr.flat(Infinity)

    arr= [ [ [1,2,3,4],[1,2,3,4],[1,2,3,4] ],
           [ [1,2,3,4],[1,2,3,4],[1,2,3,4] ] ];
          
    sum = arr.flat(Infinity).reduce((a,c)=> a+c,0);
    
    console.log(sum);  // 60

    0 讨论(0)
  • 2020-11-21 14:11

    Cool tricks here, I've got a nit pick with a lot of the safe traditional answers not caching the length of the array.

    function arraySum(array){
      var total = 0,
          len = array.length;
    
      for (var i = 0; i < len; i++){
        total += array[i];
      }
    
      return total;
    };
    
    var my_array = [1,2,3,4];
    
    // Returns 10
    console.log( arraySum( my_array ) );
    

    Without caching the length of the array the JS compiler needs to go through the array with every iteration of the loop to calculate the length, it's unnecessary overhead in most cases. V8 and a lot of modern browsers optimize this for us, so it is less of a concern then it was, but there are older devices that benefit from this simple caching.

    If the length is subject to change, caching's that could cause some unexpected side effects if you're unaware of why you're caching the length, but for a reusable function who's only purpose is to take an array and add the values together it's a great fit.

    Here's a CodePen link for this arraySum function. http://codepen.io/brandonbrule/pen/ZGEJyV

    It's possible this is an outdated mindset that's stuck with me, but I don't see a disadvantage to using it in this context.

    0 讨论(0)
提交回复
热议问题