Cómo encontrar la suma de una matriz de números

810

Dada una matriz [1, 2, 3, 4], ¿cómo puedo encontrar la suma de sus elementos? (En este caso, la suma sería 10).

Pensé que $.eachpodría ser útil, pero no estoy seguro de cómo implementarlo.

akano1
fuente
44
Esta pregunta está bajo discusión
el fantasma de Madara el
18
@ tereško La falta de voluntad para google no es un motivo válido para cerrar en Stackoverflow. Vota a favor si crees que la pregunta no está bien (re) buscada. (También a juzgar por las respuestas, este parece ser un tema muy controvertido con muchas soluciones posibles, incluidas algunas malas prácticas altamente votadas (eval), sorprendentemente)
Trilarion
8
Nota: la mayoría de las respuestas aquí esencialmente computan a[0] + a[1] + ..., lo que puede convertirse en concatenación de cadenas si la matriz tiene elementos que no son números. Por ej ['foo', 42].reduce((a,b)=>a+b, 0) === "0foo42".
Beni Cherniavsky-Paskin
No hay un reductor integrado que se pueda alimentar a Array.reduce? Pensando algo así [1,2,3].reduce(Math.sum).
Phil

Respuestas:

545

Recomendado (reducir con valor predeterminado)

Array.prototype.reduce se puede usar para iterar a través de la matriz, agregando el valor del elemento actual a la suma de los valores del elemento anterior.

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

Sin valor por defecto

Obtienes un TypeError

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

Antes de las funciones de flecha de ES6

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

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

Entradas no numéricas

Si las entradas no numéricas son posibles, ¿puede manejar eso?

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

Uso de evaluación peligroso no recomendado

Podemos usar eval para ejecutar una representación de cadena de código JavaScript. Usando la función Array.prototype.join para convertir la matriz en una cadena, cambiamos [1,2,3] en "1 + 2 + 3", que se evalúa en 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('+'))

Por supuesto, mostrar una alerta no es lo peor que podría pasar. La única razón por la que he incluido esto es como respuesta a la pregunta de Ortund, ya que no creo que se haya aclarado.

OwChallie
fuente
8
¿Sabes que esta magia reduce()aún es un 25-30% más lenta que un simple for()bucle indexado después de largos años? jsperf.com/reduce-vs-loop/4
tevemadar
Por cierto, esto tiene problemas si el número es "0"; puede interpretarse como la cadena, por cualquier razón. Agregar 1 * a + 1 * b funcionó para mí. En cuanto a la velocidad, fue más fácil de escribir y no me importa la velocidad
Peter Kay
1179

En Lisp , este sería exactamente el trabajo reduce. Verías este tipo de código:

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

Afortunadamente, en JavaScript, ¡también tenemos reduce! Lamentablemente, +es un operador, no una función. ¡Pero podemos hacerlo bonito! Aquí, mira:

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

¿No es bonito? :-)

¡Aun mejor! Si está utilizando ECMAScript 2015 (también conocido como ECMAScript 6 ), puede ser bonito:

const sum = [1, 2, 3].reduce((partial_sum, a) => partial_sum + a,0); 
console.log(sum); // 6
Florian Margaine
fuente
28
Suponiendo que todos usemos ES2015, podemos hacerlo menos detallado:[1, 2, 3].reduce((a,b)=>a+b)
Denys Séguret
1
Me pregunto si el tiempo de ejecución de reducir con una función (a, b) es comparable a una iteración y suma manual o si se incluye una sobrecarga considerable.
Trilarion
1
Creo que vale la pena mencionar que la respuesta se puede encontrar en la página que ha vinculado: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Alex Cohn
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; }
Agregaría un
2
@Black reduce una matriz en un solo valor.
Florian Margaine
205

¿Por qué no reducir? Por lo general, es un poco intuitivo, pero usarlo para encontrar una suma es bastante sencillo:

var a = [1,2,3];
var sum = a.reduce(function(a, b) { return a + b; }, 0);
Casey Rodarmor
fuente
3
IE8 no lo admite, y no parece que jQuery intente agregarlo. Sin embargo, Prototype lo tiene.
Ishmael Smyrnow
44
@Ishmael, puede usar UnderscoreJS, que recurre a la implementación del navegador si está disponible, o implementa la suya de otra manera.
Pablo Diaz
3
¿De qué se trata contra-intuitivo reduce()?
Canon el
3
@ s4nji Array.prototype.reduce() reduce una matriz a un solo valor de retorno.
canon
66
@ s4nji ... a menos que esté reduciendo una salsa, en cuyo caso la está reduciendo a lo esencial, es decir, la suma de todos los sabores sin el agua por encima. :-)
CB Du Rietz
97
var arr = [1,2,3,4];
var total=0;
for(var i in arr) { total += arr[i]; }
Ámbar
fuente
3
Esto es mucho más rápido que la solución jQuery.each () anterior.
Angry Dan el
41
@Sprog: Sin embargo, el uso (var i=0; i<arr.length; i++)es aún más rápido. E incluso entonces, el uso var sum=0; var i=arr.length; while(i--) sum += arr[i]es aún más rápido.
Riking
14
El uso de for... inbucles en matrices funciona en este caso _ coincidentemente_ y porque las matrices extienden objetos. La solución de Riking es mejor
Benjamin Gruenbaum
2
@BenjaminGruenbaum siempre que nada haya agregado propiedades enumerables al prototipo de la matriz ...
canon
1
@YSC no, no lo hace. Un for...inbucle en JavaScript toma los índices, que es un obstáculo común para los codificadores que esperan obtener los valores. (Pruébelo for(var i in [1,2,3]) { console.log(i); }en una consola.)
Ámbar
61
var total = 0;
$.each(arr,function() {
    total += this;
});
Tyler Carter
fuente
87
Por favor, por favor, use la respuesta a reducecontinuación; no declares vars mutables cuando no lo tengas también.
Bruno Grieder
99
Esta respuesta está bajo discusión
el fantasma de Madara el
11
No utilice esto, aunque sea la "respuesta aceptada"; ¡la respuesta de Florian a continuación es mucho mejor!
Andy Sinclair
12
@BrunoGrieder "No declares variables mutables cuando no es necesario" es una opinión extremadamente parcial sobre un lenguaje imperativo , no es un olor a código por ningún tramo de la imaginación. No hay absolutamente nada malo con la respuesta de Tyler, y la única diferencia entre Tyler y Florian es el estilo.
Rob
55
Desde OP: pensé que $ .each podría ser útil, pero no estoy seguro de cómo implementarlo. Quizás esto no sea lo mejor, pero responde a la solicitud del OP.
33

Si estás usando Lodash, puedes usar la función de suma

array = [1, 2, 3, 4];
sum = _.sum(array); // sum == 10
David dice reinstalar a Mónica
fuente
29

Esto es posible al recorrer todos los elementos y agregarlos en cada iteración a una sumvariable.

var array = [1, 2, 3];

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

JavaScript no conoce el alcance del bloque, por sumlo que será accesible:

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

Lo mismo que arriba, sin embargo anotado y preparado como una función simple:

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;
}
yckart
fuente
12
Si bien es inteligente, me parece que el código que declara sumfuera del ciclo es mucho más legible.
Beni Cherniavsky-Paskin
@ BeniCherniavsky-Paskin Sí, lo mismo aquí ... No sé por qué lo hice así ese día ... Sin embargo, ¡lo dejaré como está! Es solo un ejemplo de cómo podríamos ... ;)
yckart
Desde ES6, javascript conoce el alcance del bloque con consty let. Entonces puedes declarar sumfuera del forciclo como let sum = 0;. También puede almacenar en caché la longitud de la matriz antes del ciclo comoconst length = array.length;
KSK
23
arr.reduce(function (a, b) {
    return a + b;
});

Referencia: Array.prototype.reduce ()

onhout
fuente
66
Esto fallará si arres así [].
77
Agregue un valor predeterminado, así:arr.reduce(function (a, b) { return a + b; }, 0);
Ngz
15
// Given array 'arr'
var i = arr.length;
var sum = 0;
while (--i) sum += arr[i];

Esto tomará en promedio 1.57 ms / carrera (medido más de 1000 carreras en una matriz de 100 números normales aleatorios), en comparación con 3.604 ms / carrera con el eval()método anterior y 2.151 ms / carrera con un estándar para (i, longitud, ++ ) lazo.

Nota metodológica: esta prueba se ejecutó en un servidor de Google Apps Script, por lo que sus motores de JavaScript son prácticamente iguales a los de Chrome.

EDITAR: en --ilugar de i--guardar 0,12 ms cada ejecución (i-- es 1.7)

EDITAR: Santo improperio, no importa esta publicación completa. Use el método reduce () mencionado anteriormente, es solo 1 ms / ejecución.

Riking
fuente
1
Me encantan los tiempos que usaste. Tu respuesta no solo dice "¡Elígeme, soy el mejor!" En cambio, nos muestra por qué . De todos modos, el while (--i) do_somethingpodría funcionar para otras cosas también.
Programas Redwolf
var sum = arr[0]
noobninja el
12

¿Alguien que busca una línea funcional como yo? Toma esto:

sum= arr.reduce(function (a, b) {return a + b;}, 0);
geek-merlin
fuente
Puede agregar un valor inicial para reducir como el segundo arr.reduce(function(a, b) { return a + b;}, 0);
parámetro
¡Gracias! Lo incorporaré.
geek-merlin
12

OK, imagina que tienes esta matriz a continuación:

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

Comencemos a buscar muchas maneras diferentes de hacerlo, ya que no pude encontrar ninguna respuesta completa aquí:

1) Uso de reduce incorporado ()

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

2) Utilizando for loop

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) Usando el bucle while

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

4) Usar una matriz para cada

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

y llámalo así:

total(arr); //return 10

No se recomienda crear un prototipo de este tipo para Array ...

Alireza
fuente
11

Enfoque divertido:

eval([1,2,3].join("+"))
electrón
fuente
55
¿Podría ampliar esta respuesta explicando qué está sucediendo en este código? Por que funciona ¿Qué hace exactamente? Estas cosas ayudan a mejorar la calidad de la respuesta.
Ortund
@ user40521 ya ha respondido esto de la manera que pienso. No lo vi
electrón
Si bien esto es breve y dulce, y ciertamente interesante, también es muy ineficiente. Usar reducees definitivamente preferible para la mayoría, si no para todos, los casos.
Ninjakannon
Errm,[1,"2;YourProgram.ripToShreds();3",4]
Programas Redwolf
Así que estoy obteniendo NaNcuando intento eval(['alert("removing your computer")',2,3].join("+"))respuesta incorrecta 0/10
pie6k
10

Una solución estándar de 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 */

Esto funciona para mí (el resultado debería ser 5). Espero que no haya una desventaja oculta en este tipo de solución.

nano
fuente
1
Además, cualquier programador de C o Java podría entender esto.
Audrius Meskauskas
con el simple propósito de resumir todos los valores de la llanura sencilla de edad para el bucle no tiene rivales en términos de tiempo de ejecución
fedeghe
El único problema es que es un poco molesto cuando tienes 20 para bucles todos anidados entre sí
Redwolf Programs
7
var totally = eval(arr.join('+'))

De esa manera puedes poner todo tipo de cosas exóticas en la matriz.

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

Solo estoy medio bromeando.

usuario40521
fuente
26
Estoy medio riendo
caub
eval(['alert("removing your computer")',2,3].join("+"))
pie6k
7

Soy un principiante con JavaScript y la codificación en general, pero descubrí que una forma simple y fácil de sumar los números en una matriz es así:

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

Básicamente, quería contribuir con esto porque no veía muchas soluciones que no usaran funciones integradas, y este método es fácil de escribir y entender.

CandyPaintedRIMS
fuente
1
¿Cómo es esto diferente de esta respuesta 2012 o esta respuesta 2014 ? Hay dos soluciones que no has visto.
Dan Dascalescu
5

Un pequeño fragmento de código JavaScript haría este trabajo:

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)
Timur Zhilenkov
fuente
5

Algunas personas han sugerido agregar un .sum()método al Array.prototype. Esto generalmente se considera una mala práctica, por lo que no estoy sugiriendo que lo haga.

Si aún insiste en hacerlo, esta es una forma sucinta de escribirlo:

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

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

Tenga en cuenta que la función agregada al prototipo está utilizando una mezcla de la función ES5 y ES6 y la sintaxis de flecha. Se functiondeclara que permite que el método obtenga el thiscontexto del Arrayque está operando. Usé la =>brevedad dentro de la reducellamada.

Chico
fuente
5

Usa un forbucle:

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

O incluso un forEachbucle:

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

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

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

Para simplificar, use reduce:

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

console.log(result); // Should give 100
JuicY_Burrito
fuente
4

No es necesario initial value! Porque si no initial valuese pasa, callback functionno se invoca en el primer elemento de la lista, y el primer elemento se pasa como initial value. Muy c OO l característica :)

[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
Yas
fuente
4

Aquí hay una solución elegante de una sola línea que utiliza el algoritmo de pila , aunque uno puede tomar un tiempo para comprender la belleza de esta implementación.

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

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

Básicamente, la función acepta una matriz y verifica si la matriz contiene exactamente un elemento. Si es falso, saca el último elemento de la pila y devuelve la matriz actualizada.

La belleza de este fragmento es que la función incluye la arr[0]comprobación para evitar bucles infinitos. Una vez que alcanza el último elemento, devuelve la suma completa.

Rex Low
fuente
4

Puede combinar el método reduce () con la expresión lambda:

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

Utilizar reduce

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

let sum = arr.reduce((v, i) => (v + i));

console.log(sum);

Damien Asseya
fuente
3

Vi todas las respuestas para la solución 'reducir'

var array = [1,2,3,4]
var total = 0
for (var i = 0; i < array.length; i++) {
    total += array[i]
}
console.log(total)
Adrian Swifter
fuente
3

Exactitud

Ordene la matriz y comience la suma de los números más pequeños (el fragmento muestra la diferencia con no ordenar)

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

Para una matriz multidimensional de números, use arr.flat(Infinity)

Kamil Kiełczewski
fuente
2

Trucos geniales aquí, tengo una selección de liendres con muchas de las respuestas tradicionales seguras que no almacenan en caché la longitud de la matriz.

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

Sin almacenar en caché la longitud de la matriz, el compilador JS necesita recorrer la matriz con cada iteración del bucle para calcular la longitud, es una sobrecarga innecesaria en la mayoría de los casos. V8 y muchos navegadores modernos optimizan esto para nosotros, por lo que es menos preocupante de lo que era, pero hay dispositivos más antiguos que se benefician de este simple almacenamiento en caché.

Si la longitud está sujeta a cambios, el almacenamiento en caché puede causar algunos efectos secundarios inesperados si no sabe por qué está almacenando en caché la longitud, pero para una función reutilizable cuyo único propósito es tomar una matriz y agregar los valores juntos es un Gran ajuste.

Aquí hay un enlace CodePen para esta función arraySum. http://codepen.io/brandonbrule/pen/ZGEJyV

Es posible que se trate de una mentalidad desactualizada, pero no veo ninguna desventaja en usarla en este contexto.

Brandon Brule
fuente
El problema del almacenamiento en caché de la longitud es un arenque rojo. Los motores JS optimizarán esto para usted sin parpadear.
2

Esas son respuestas realmente geniales, pero por si los números están en secuencia, como en la pregunta (1,2,3,4), puede hacerlo fácilmente aplicando la fórmula (n * (n + 1)) / 2 donde n es el último número

Santosh
fuente
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
ostranenie
fuente
¿Este código elimina su sistema operativo? ¿O me envía su información personal?
2

Esto es mucho más fácil

function sumArray(arr) {
    var total = 0;
    arr.forEach(function(element){
        total += element;
    })
    return total;
}

var sum = sumArray([1,2,3,4])

console.log(sum)
Jakub Gawel
fuente
2

Un ejemplo de método simple:

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]));
Sifiso Nkabinde
fuente