如何找到数字数组的总和


808

给定一个数组[1, 2, 3, 4],如何找到其元素的总和?(在这种情况下,总和为10。)

我以为$.each可能有用,但是我不确定如何实现它。


4
这个问题是在元的讨论
斑的幽灵

18
@tereško不愿意Google并不是Stackoverflow上的有效关闭理由。如果您认为问题未得到很好(重新)搜索,请投下反对票。(令人惊讶的是,从答案来看-这似乎是一个备受争议的话题,提供了许多可能的解决方案,其中包括一些被高度评价的不良做法(评估)-令人惊讶。)
Trilarion

8
注意:这里的大多数答案本质上是compute a[0] + a[1] + ...,如果数组包含非数字元素,则可以转换为字符串连接。例如['foo', 42].reduce((a,b)=>a+b, 0) === "0foo42"
贝尼·切尔尼亚夫斯基-帕斯金

没有内置的reducer可以提供给Array.reduce?思考类似[1,2,3].reduce(Math.sum)
Phil

Answers:


540

推荐(减少默认值)

Array.prototype.reduce可用于遍历数组,将当前元素值添加到先前元素值的总和中。

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

没有默认值

您收到TypeError

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

在ES6的箭头功能之前

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

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

非数字输入

如果非数字是可能的输入,您可能要处理呢?

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

不建议危险的评估使用

我们可以使用eval执行JavaScript代码的字符串表示形式。使用Array.prototype.join函数将数组转换为字符串,我们将[1,2,3]更改为“ 1 + 2 + 3”,其结果为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('+'))

当然,显示警报并不是可能发生的最糟糕的事情。我将其包括在内的唯一原因是作为对Ortund问题的回答,因为我认为这没有得到澄清。


8
您是否知道,经过多年的发展,这种魔术reduce()仍然比简单的索引for()循环慢25-30%?jsperf.com/reduce-vs-loop/4
tevemadar,

顺便说一下,如果数字为“ 0”,则会出现问题-无论出于何种原因,它都可能被解释为字符串。加1 * a + 1 * b对我有用。至于速度,这更容易编写,我不在乎速度
Peter Kay

1179

Lisp中,这正是要完成的工作reduce。您会看到以下代码:

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

幸运的是,在JavaScript中,我们还有reduce!不幸的是,它+是一个运算符,而不是一个函数。但是我们可以使其漂亮!在这里,看看:

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

那不是很漂亮吗?:-)

更好!如果您使用的是ECMAScript 2015(又名ECMAScript 6),它可能会很漂亮:

const sum = [1, 2, 3].reduce((partial_sum, a) => partial_sum + a,0); 
console.log(sum); // 6

28
假设我们都使用ES2015,则可以使它不那么冗长:[1, 2, 3].reduce((a,b)=>a+b)
DenysSéguret2015年

1
我想知道用函数(a,b)进行reduce的执行时间是否可与手动迭代和求和相媲美,或者是否包含相当大的开销?
Trilarion'1

1
我认为,这是值得一提的是,答案实际上可以你的链接页面上找到:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
亚历克斯·科恩

2
我将几个方法添加到数组:Array.prototype.sum = function() { return this.reduce((a,b) => a+b, 0); } Array.prototype.avg = function() { return this.reduce((a,b) => a+b, 0)/this.length; }
pilat

2
@Black将数组简化为单个值。
Florian Margaine '18 -4-29

204

为什么不减少?通常,这有点反直观,但使用它来查找总和非常简单:

var a = [1,2,3];
var sum = a.reduce(function(a, b) { return a + b; }, 0);

3
IE8不支持它,而且看起来也不像jQuery打算添加它。但是,原型具有它。
Ishmael Smyrnow 2012年

4
@Ishmael,您可以使用UnderscoreJS,如果有的话,它可以使用浏览器的实现,否则,可以使用自己的实现。
Pablo Diaz

3
违反直觉的是reduce()什么?
佳能

3
@ s4nji Array.prototype.reduce() 数组减少为单个返回值。
佳能

6
@ s4nji ...除非您要减少调味料-在这种情况下,您要将其归结为调味料的要点,即所有调味料的总和,而无需加水。:-)
CB Du Rietz

97
var arr = [1,2,3,4];
var total=0;
for(var i in arr) { total += arr[i]; }

3
这比上面的jQuery.each()解决方案要快得多。
愤怒的丹,

41
@Sprog:但是,使用(var i=0; i<arr.length; i++)速度甚至更快。即使这样,使用var sum=0; var i=arr.length; while(i--) sum += arr[i]速度仍然更快。
2012年

14
for... in在这种情况下,_巧合地_可以在数组上使用循环,因为数组扩展了对象。Riking的解决方案更好
Benjamin Gruenbaum

2
@BenjaminGruenbaum提供了什么都没有为数组的原型添加可枚举的属性……
佳能

1
@YSC不,不是。一个for...in在JavaScript中环路采取指数,这对于期望得到的值编码器共同绊脚石。(for(var i in [1,2,3]) { console.log(i); }在控制台中尝试。)
琥珀色

61
var total = 0;
$.each(arr,function() {
    total += this;
});

87
请,请使用reduce下面的答案;如果没有,也不要声明可变的var。
Bruno Grieder

9
这个答案正在讨论中
马达拉的幽灵“

11
请不要使用它,即使它是“可接受的答案”;下面弗洛里安的答案要好得多!
安迪·辛克莱

12
@BrunoGrieder“不必声明时不要声明可变的var”是关于命令式语言的一种极端偏见,无论凭什么想象力,它几乎都不是代码气味。泰勒的答案绝对没有错,泰勒和弗洛里安之间的唯一区别是风格。
罗布

5
来自OP:我认为$ .each可能有用,但是我不确定如何实现它。这可能不是最好的方法,但请回答OP的要求。


29

这可以通过遍历所有项目,并在每次迭代sum中将它们添加到-variable中来实现。

var array = [1, 2, 3];

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

JavaScript不知道块作用域,因此sum可以访问:

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

与上面相同,但是已注释并准备为简单函数:

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;
}

12
虽然很聪明,但我发现sum在循环外声明的代码更具可读性。
贝尼·切尔尼亚夫斯基-帕斯金

@ BeniCherniavsky-Paskin是的,在这里...不知道为什么那天我这样做了...但是,我会照原样做!这只是我们可能如何做的一个示例... ;)
yckart

从ES6开始,javascript确实知道使用const和进行块作用域let。因此,您可以sumfor循环外部将声明为let sum = 0;。您还可以在循环之前缓存数组长度,例如const length = array.length;
KSK


15
// Given array 'arr'
var i = arr.length;
var sum = 0;
while (--i) sum += arr[i];

平均运行时间为1.57毫秒(在100个随机正常数的数组上测量1000次运行),而上述eval()方法的运行时间为3.604毫秒,标准的(i,length,++ 运行时间为2.151毫秒)循环。

方法论说明:该测试在Google Apps脚本服务器上运行,因此其javascript引擎与Chrome几乎相同。

编辑:--i而不是i--每次运行节省0.12毫秒(i--是1.7)

编辑:神圣的咒骂,不要介意这整个职位。使用上面提到的reduce()方法,每次运行只有1毫秒。


1
我喜欢你使用的时间。您的回答不只是说:“接我,我最好!” 相反,它向我们显示了原因。无论如何,这while (--i) do_something可能也适用于其他事情。
Redwolf Programs '18 -10-25

var sum = arr[0]
noobninja


12

是否有人在寻找像我这样的功能齐全的内衬?拿着它:

sum= arr.reduce(function (a, b) {return a + b;}, 0);

您可以将reduce的初始值添加为第二个参数:arr.reduce(function(a, b) { return a + b;}, 0);
Ngz

谢谢!我将合并。
geek-merlin

12

有趣的方法:

eval([1,2,3].join("+"))

5
请您解释一下这段代码中发生的事情,以此扩展您的答案?为什么行得通?它到底是做什么的?这些东西有助于提高答案的质量。
Ortund '16

@ user40521已经按照我的方式回答了。我没看到
电子版

尽管这是简短而有趣的,而且当然很有趣,但它的效率也很低。reduce对于大多数(如果不是全部)情况,绝对优选使用。
Ninjakannon

错误,[1,"2;YourProgram.ripToShreds();3",4]
Redwolf节目

所以我NaN在尝试eval(['alert("removing your computer")',2,3].join("+"))错误答案0/10 时得到
pie6k

12

好吧,假设您在下面有这个数组:

const arr = [1, 2, 3, 4];

让我们开始研究实现它的许多不同方法,因为我在这里找不到任何全面的答案:

1)使用内置的reduce()

function total(arr) {
  if(!Array.isArray(arr)) return;
  return arr.reduce((a, v)=>a + v);
}

2)使用for循环

function total(arr) {
  if(!Array.isArray(arr)) return;
  let totalNumber = 0;
  for (let i=0,l=arr.length; i<l; i++) {
     totalNumber+=arr[i];
  }
  return totalNumber;
}

3)使用while循环

function total(arr) {
  if(!Array.isArray(arr)) return;
  let totalNumber = 0, i=-1;
  while (++i < arr.length) {
     totalNumber+=arr[i];
  }
  return totalNumber;
}

4)使用数组forEach

function total(arr) {
  if(!Array.isArray(arr)) return;
  let sum=0;
  arr.forEach(each => {
    sum+=each;
  });
  return sum;
};

并这样称呼它:

total(arr); //return 10

不建议将类似这样的东西原型化为Array ...


10

标准的JavaScript解决方案:

var addition = [];
addition.push(2);
addition.push(3);

var total = 0;
for (var i = 0; i < addition.length; i++)
{
    total += addition[i];
}
alert(total);          // Just to output an example
/* console.log(total); // Just to output an example with Firebug */

这对我有用(结果应该是5)。我希望这种解决方案没有隐藏的缺点。


1
而且,任何C或Java程序员都将能够理解这一点。
Audrius Meskauskas,2016年

出于汇总所有值的简单目的,简单普通的for循环在执行时间方面没有竞争对手
fedeghe

唯一的问题是,当您有20个for循环都相互嵌套时,这会很烦人
Redwolf Programs'Oct

7
var totally = eval(arr.join('+'))

这样,您可以将各种奇特的东西放入数组中。

var arr = ['(1/3)','Date.now()','foo','bar()',1,2,3,4]

我只是在开玩笑。


26
我半
笑不出来

eval(['alert("removing your computer")',2,3].join("+"))
pie6k

7

我一般是JavaScript和编码的初学者,但是我发现一种简单易行的方法将数组中的数字相加是这样的:

    var myNumbers = [1,2,3,4,5]
    var total = 0;
    for(var i = 0; i < myNumbers.length; i++){
        total += myNumbers[i];
    }

基本上,我想为此做出贡献,因为我没有看到很多不使用内置函数的解决方案,而且这种方法易于编写和理解。


1
这与2012年2014年的答案有何不同?您还没有看到两种解决方案。
Dan Dascalescu

5

一小段JavaScript代码即可完成此工作:

var numbers = [1,2,3,4];
var totalAmount = 0;

for (var x = 0; x < numbers.length; x++) {

    totalAmount += numbers[x];
}

console.log(totalAmount); //10 (1+2+3+4)

5

少数人建议向中添加一个.sum()方法Array.prototype。通常认为这是不良做法,因此我不建议您这样做。

如果您仍然坚持这样做,那么这是一种简洁的编写方式:

Array.prototype.sum = function() {return [].reduce.call(this, (a,i) => a+i, 0);}

然后: [1,2].sum(); // 3

请注意,添加到原型的函数使用的是ES5和ES6函数以及箭头语法的混合体。该function声明允许方法来获取this从上下文Array,你操作上。=>为了方便起见,我在reduce电话中使用了。


5

使用for循环:

const array = [1, 2, 3, 4];
let result = 0;

for (let i = 0; i < array.length - 1; i++) {
  result += array[i];
}

console.log(result); // Should give 10

甚至forEach循环:

const array = [1, 2, 3, 4];
let result = 0;

array.forEach(number => {
  result += number;
})

console.log(result); // Should give 10

为简单起见,请使用reduce

const array = [10, 20, 30, 40];
const add = (a, b) => a + b
const result = array.reduce(add);

console.log(result); // Should give 100

4

没必要initial value!因为如果没有initial value传递,callback function则不会在列表的第一个元素上调用,而是将第一个元素作为传递initial value。非常有趣的功能:)

[1, 2, 3, 4].reduce((a, x) => a + x) // 10
[1, 2, 3, 4].reduce((a, x) => a * x) // 24
[1, 2, 3, 4].reduce((a, x) => Math.max(a, x)) // 4
[1, 2, 3, 4].reduce((a, x) => Math.min(a, x)) // 1

4

这是一种使用堆栈算法的优雅的单线解决方案,尽管您可能需要一些时间来了解此实现的优点。

const getSum = arr => (arr.length === 1) ? arr[0] : arr.pop() + getSum(arr);

getSum([1, 2, 3, 4, 5]) //15

基本上,该函数接受一个数组并检查该数组是否仅包含一项。如果为false,则将最后一项从堆栈中弹出,并返回更新后的数组。

此代码段的优点是该函数包括arr[0]检查以防止无限循环。一旦到达最后一项,它将返回全部金额。


4

您可以将reduce()方法与lambda表达式结合使用:

[1, 2, 3, 4].reduce((accumulator, currentValue) => accumulator + currentValue);



3

准确性

排序数组和起始和形成最小的数字(摘要显示与非排序的差异)

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

对于数字的多维数组,请使用 arr.flat(Infinity)


2

这里的技巧很酷,我选择了很多安全的传统答案,而不用担心数组的长度。

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

在不缓存数组长度的情况下,JS编译器需要在每次循环迭代时都遍历数组以计算长度,在大多数情况下这是不必要的开销。V8和许多现代浏览器为我们优化了此功能,因此,它比以前少了一个问题,但是有一些较旧的设备受益于这种简单的缓存。

如果长度可能会发生变化,那么如果您不知道为什么要缓存长度,则缓存的操作可能会导致一些意外的副作用,但是对于可重用的函数,其唯一目的是获取数组并将值相加在一起,这就是非常适合。

这是此arraySum函数的CodePen链接。 http://codepen.io/brandonbrule/pen/ZGEJyV

这可能是我束手无策的一种过时的心态,但我认为在这种情况下使用它并不不利。


缓存长度的问题是红色鲱鱼。JS引擎将为您优化此过程,而不会闪烁。

2

这些确实是很好的答案,但是万一如果数字按问题(1,2,3,4)的顺序排列,您可以通过应用公式(n *(n + 1))/ 2轻松地做到这一点n是最后一个数字


2
Object.defineProperty(Object.prototype, 'sum', {
    enumerable:false,
    value:function() {
        var t=0;for(var i in this)
            if (!isNaN(this[i]))
                t+=this[i];
        return t;
    }
});

[20,25,27.1].sum()                 // 72.1
[10,"forty-two",23].sum()          // 33
[Math.PI,0,-1,1].sum()             // 3.141592653589793
[Math.PI,Math.E,-1000000000].sum() // -999999994.1401255

o = {a:1,b:31,c:"roffelz",someOtherProperty:21.52}
console.log(o.sum());              // 53.519999999999996

此代码会删除您的操作系统吗?还是会将您的个人信息发送给我?


2

一个简单的方法示例:

function add(array){
    var arraylength = array.length;
    var sum = 0;
    for(var timesToMultiply = 0; timesToMultiply<arraylength; timesToMultiply++){
        sum += array[timesToMultiply];
    }

    return sum;
}

console.log(add([1, 2, 3, 4]));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.