Come trovare la somma di una matrice di numeri


810

Dato un array [1, 2, 3, 4], come posso trovare la somma dei suoi elementi? (In questo caso, la somma sarebbe 10.)

Ho pensato che $.eachpotesse essere utile, ma non sono sicuro di come implementarlo.


4
Questa domanda è in fase di discussione
Madara's Ghost

18
@ tereško La mancanza di volontà nei confronti di Google non è un motivo valido vicino a StackOverflow. Si prega di sottovalutare se si ritiene che la domanda non sia (ri) cercata bene. (Anche a giudicare dalle risposte - questo sembra essere un argomento molto controverso con molte possibili soluzioni tra cui alcune cattive pratiche altamente votate (eval) - sorprendentemente.)
Trilarion

8
Nota: qui la maggior parte delle risposte essenzialmente calcola a[0] + a[1] + ..., che può trasformarsi in concatenazione di stringhe se l'array ha elementi non numerici. Es ['foo', 42].reduce((a,b)=>a+b, 0) === "0foo42".
Beni Cherniavsky-Paskin,

Nessun riduttore integrato può essere alimentato ad Array.reduce? Pensando a qualcosa del genere [1,2,3].reduce(Math.sum).
Phil

Risposte:


545

Consigliato (riduci con valore predefinito)

Array.prototype.reduce può essere utilizzato per iterare l'array, aggiungendo il valore dell'elemento corrente alla somma dei valori dell'elemento precedente.

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

Senza valore predefinito

Ottieni un TypeError

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

Prima delle funzioni freccia di ES6

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

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

Ingressi non numerici

Se sono possibili input non numerici, potresti voler gestirlo?

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 pericoloso non raccomandato non raccomandato

Possiamo usare eval per eseguire una rappresentazione in forma di stringa del codice JavaScript. Usando la funzione Array.prototype.join per convertire l'array in una stringa, cambiamo [1,2,3] in "1 + 2 + 3", che valuta 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('+'))

Naturalmente la visualizzazione di un avviso non è la cosa peggiore che potrebbe accadere. L'unica ragione per cui ho incluso questo è come risposta alla domanda di Ortund in quanto non credo che sia stata chiarita.


8
Sai che questa magia con reduce()è ancora del 25-30% più lenta di un semplice for()ciclo indicizzato dopo lunghi anni? jsperf.com/reduce-vs-loop/4
tevemadar,

Questo può incorrere in problemi se il numero è "0" a proposito - potrebbe essere interpretato come la stringa, per qualsiasi motivo. L'aggiunta di 1 * a + 1 * b ha funzionato per me. Per quanto riguarda la velocità, questo è stato più facile da scrivere e non mi interessa la velocità
Peter Kay il

1179

A Lisp , questo sarebbe esattamente il lavoro per reduce. Vedresti questo tipo di codice:

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

Fortunatamente, in JavaScript, abbiamo anche reduce! Sfortunatamente, +è un operatore, non una funzione. Ma possiamo renderlo carino! Ecco, guarda:

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

Non è carino? :-)

Anche meglio! Se stai usando ECMAScript 2015 (aka ECMAScript 6 ), può essere così carino:

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

28
Supponendo che tutti usiamo ES2015, possiamo renderlo meno dettagliato:[1, 2, 3].reduce((a,b)=>a+b)
Denys Séguret,

1
Mi chiedo se il tempo di esecuzione di ridurre con una funzione (a, b) sia paragonabile a una iterazione e una somma manuali o se sia incluso un notevole sovraccarico?
Trilarion

1
Credo che valga la pena ricordare che la risposta può essere effettivamente trovata nella pagina che hai collegato: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Alex Cohn

2
Aggiungerei un paio di metodi 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; }
all'array

2
@ Nero riduce un array in un singolo valore.
Florian Margaine,

205

Perché non ridurre? Di solito è un po 'intuitivo, ma usarlo per trovare una somma è piuttosto semplice:

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

3
IE8 non lo supporta e non sembra che jQuery intenda aggiungerlo. Tuttavia, Prototype ce l'ha.
Ishmael Smyrnow,

4
@Ishmael, puoi usare UnderscoreJS, che ricorre all'implementazione del browser se disponibile, o implementa il suo altrimenti.
Pablo Diaz,

3
Cosa c'è di contro intuitivo reduce()?
canone

3
@ s4nji Array.prototype.reduce() riduce un array a un singolo valore di ritorno.
canone il

6
@ s4nji ... a meno che tu non stia riducendo una salsa, nel qual caso la stai bollando fino all'essenziale, cioè la somma di tutti i sapori senza il sovraccarico di acqua. :-)
CB Du Rietz

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

3
Questo è molto più veloce della soluzione jQuery.each () sopra.
Angry Dan,

41
@Sprog: Tuttavia, l'utilizzo (var i=0; i<arr.length; i++)è ancora più veloce. E anche allora, l'utilizzo var sum=0; var i=arr.length; while(i--) sum += arr[i]è ancora più veloce.
Riking

14
L'uso di for... inloop su array funziona in questo caso _ per coincidenza_ e perché gli array estendono gli oggetti. La soluzione di Riking è migliore
Benjamin Gruenbaum

2
@BenjaminGruenbaum ha fornito che nulla ha aggiunto proprietà enumerabili al prototipo di array ...
canone

1
@YSC no, non lo è. Un for...inciclo in JavaScript prende gli indici, che è un ostacolo comune per i programmatori che prevedono di ottenere i valori. (Prova for(var i in [1,2,3]) { console.log(i); }in una console.)
Amber

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

87
Per favore, per favore, per favore usa la risposta con reducesotto; non dichiarare variabili mutabili quando non ce l'hai.
Bruno Grieder,

9
Questa risposta è in fase di discussione
Madara's Ghost

11
Si prega di non utilizzare questo, anche se è la "risposta accettata"; la risposta di Florian qui sotto è molto meglio!
Andy Sinclair,

12
@BrunoGrieder "Non dichiarare variabili mutabili quando non è necessario" è un'opinione estremamente distorta su un linguaggio imperativo , non è quasi un odore di codice da parte di un tratto dell'immaginazione. Non c'è assolutamente nulla di sbagliato nella risposta di Tyler, e l'unica differenza tra Tyler e Florian è lo stile.
Rob

5
Da OP: ho pensato che $ .each potesse essere utile, ma non sono sicuro di come implementarlo. Questo forse non è il migliore, ma rispondi alla richiesta del PO.


29

Ciò è possibile sumeseguendo il ciclo su tutti gli elementi e aggiungendoli su ogni iterazione in una variabile.

var array = [1, 2, 3];

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

JavaScript non conosce l'ambito del blocco, quindi sumsarà accessibile:

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

Come sopra, comunque annotato e preparato come una semplice funzione:

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
Sebbene intelligente, troverei il codice che dichiara sumfuori dal ciclo molto più leggibile.
Beni Cherniavsky-Paskin,

@ BeniCherniavsky-Paskin Sì, lo stesso qui ... Non so perché l'ho fatto così quel giorno ... Tuttavia, lo lascerò così com'è! È solo un esempio di come potremmo ... ;)
yckart

Da ES6, JavaScript conosce l'ambito del blocco con conste let. Quindi puoi dichiarare sumal di fuori del forciclo come let sum = 0;. Puoi anche memorizzare nella cache la lunghezza dell'array prima del ciclo comeconst length = array.length;
KSK

23
arr.reduce(function (a, b) {
    return a + b;
});

Riferimento: Array.prototype.reduce ()


6
Questo fallirà se lo arrè [].

7
Aggiungi un valore predefinito, in questo modo: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];

Ciò richiederà in media 1,57 ms / corsa (misurata su 1000 corse su un array di 100 numeri normali casuali), rispetto a 3,604 ms / corsa con il eval()metodo sopra e 2,151 ms / corsa con uno standard per (i, lunghezza, ++ ) ciclo continuo.

Nota metodologica: questo test è stato eseguito su un server Script di Google Apps, quindi i loro motori javascript sono praticamente gli stessi di Chrome.

EDIT: --iinvece di i--risparmiare 0,12 ms a ogni corsa (i-- è 1,7)

EDIT: Holy expletive, non importa questo intero post. Utilizzare il metodo di riduzione () sopra menzionato, è solo 1 ms / corsa.


1
Adoro i tempi che hai usato. La tua risposta non dice semplicemente "Pick me, I'm best!" Ci mostra invece perché . Comunque, while (--i) do_somethingpotrebbe funzionare anche per altre cose.
Programmi Redwolf,

var sum = arr[0]
Noobninja,


12

Chiunque cerchi un oneliner funzionale come me? Prendi questo:

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

È possibile aggiungere un valore iniziale per ridurre come secondo parametro:arr.reduce(function(a, b) { return a + b;}, 0);
Ngz

Grazie! lo incorporerò.
geek-merlin,

12

OK, immagina di avere questo array sotto:

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

Cominciamo a cercare in molti modi diversi per farlo poiché non sono riuscito a trovare una risposta completa qui:

1) Utilizzo di ridurre () incorporato

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

2) Utilizzo per ciclo

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) Utilizzo del ciclo while

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

4) Utilizzo dell'array per ogni

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

e chiamalo così:

total(arr); //return 10

Non è consigliabile prototipare qualcosa del genere su Array ...


11

Approccio divertente:

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

5
Per favore, potresti espandere questa risposta spiegando cosa sta succedendo in questo codice? Perché funziona Che cosa fa esattamente? Queste cose aiutano a migliorare la qualità della risposta.
Ortund,

@ user40521 ha già risposto nel modo in cui penso. Non l'ho visto
elettrone,

Anche se questo è breve e dolce e certamente interessante, è anche molto inefficiente. L'uso reduceè sicuramente preferibile per la maggior parte, se non per tutti, i casi.
Ninjakannon,

Errm,[1,"2;YourProgram.ripToShreds();3",4]
Programmi Redwolf

Quindi sto ottenendo NaNquando eval(['alert("removing your computer")',2,3].join("+"))
provo la

10

Una soluzione JavaScript standard:

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 */

Questo funziona per me (il risultato dovrebbe essere 5). Spero non ci siano svantaggi nascosti in questo tipo di soluzione.


1
Inoltre, qualsiasi programmatore C o Java sarebbe in grado di capirlo.
Audrius Meskauskas l'

al semplice scopo di riassumere tutti i valori, il semplice semplice vecchio per loop non ha rivali in termini di tempo di esecuzione
fedeghe,

L'unico problema è che è un po 'fastidioso quando hai 20 per i loop tutti nidificati l'uno nell'altro
Programmi Redwolf

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

In questo modo puoi mettere tutti i tipi di cose esotiche nella matrice.

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

Sto solo scherzando a metà.


26
Sto ridendo a metà
caub

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

7

Sono un principiante con JavaScript e la codifica in generale, ma ho scoperto che un modo semplice e facile per sommare i numeri in un array è il seguente:

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

Fondamentalmente, volevo contribuire perché non vedevo molte soluzioni che non utilizzano funzioni integrate e questo metodo è facile da scrivere e capire.


1
In che modo differisce da questa risposta del 2012 o questa risposta del 2014 ? Ci sono due soluzioni che non hai visto.
Dan Dascalescu,

5

Un breve pezzo di codice JavaScript farebbe questo lavoro:

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

Alcune persone hanno suggerito di aggiungere un .sum()metodo a Array.prototype. Questa è generalmente considerata una cattiva pratica, quindi non sto suggerendo di farlo.

Se insisti ancora a farlo, allora questo è un modo sintetico di scriverlo:

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

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

Si noti che la funzione aggiunta al prototipo utilizza una combinazione di funzione ES5 ed ES6 e sintassi della freccia. Il functionè dichiarato per consentire il metodo per ottenere il thiscontesto dal Arrayche si opera su. Ho usato il =>per brevity all'interno della reducechiamata.


5

Usa un forciclo:

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 anche un forEachciclo:

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

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

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

Per semplicità, utilizzare 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

Non è necessario initial value! Perché se no initial valueviene passato, callback functionnon viene invocato sul primo elemento dell'elenco e il primo elemento viene invece passato come initial value. Funzionalità molto interessante :)

[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

Ecco un'elegante soluzione one-liner che utilizza l' algoritmo stack , anche se potrebbe essere necessario del tempo per capire la bellezza di questa implementazione.

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

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

Fondamentalmente, la funzione accetta un array e controlla se l'array contiene esattamente un elemento. Se falso, estrae l'ultimo elemento dallo stack e restituisce l'array aggiornato.

Il bello di questo frammento è che la funzione include il arr[0]controllo per evitare cicli infiniti. Una volta raggiunto l'ultimo elemento, restituisce l'intera somma.


4

È possibile combinare il metodo di riduzione () con l'espressione lambda:

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


3

ho visto tutte le risposte che cercavano la soluzione "riduci"

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

3

Precisione

Ordina l'array e avvia la somma dal numero più piccolo (lo snippet mostra la differenza con non ordinamento)

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

Per la matrice multidimensionale di numeri usare arr.flat(Infinity)


2

Trucchi fantastici qui, ho una scelta netta con un sacco di risposte tradizionali sicure che non memorizzano nella cache l'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 ) );

Senza memorizzare nella cache la lunghezza dell'array, il compilatore JS deve passare attraverso l'array ad ogni iterazione del ciclo per calcolare la lunghezza, nella maggior parte dei casi non è necessario sovraccarico. V8 e molti browser moderni lo ottimizzano per noi, quindi è meno preoccupante di allora, ma ci sono dispositivi più vecchi che beneficiano di questa semplice memorizzazione nella cache.

Se la lunghezza è soggetta a modifiche, la memorizzazione nella cache potrebbe causare alcuni effetti collaterali imprevisti se non si è consapevoli del motivo per cui si memorizza la lunghezza nella cache, ma per una funzione riutilizzabile il cui unico scopo è prendere un array e sommare i valori insieme è un ottima vestibilità.

Ecco un link CodePen per questa funzione arraySum. http://codepen.io/brandonbrule/pen/ZGEJyV

È possibile che questa sia una mentalità obsoleta che mi è bloccata, ma non vedo uno svantaggio nell'usarla in questo contesto.


Il problema della memorizzazione nella cache della lunghezza è un'aringa rossa. I motori JS lo ottimizzeranno senza battere ciglio.

2

Queste sono risposte davvero fantastiche, ma nel caso in cui i numeri siano in sequenza come nella domanda (1,2,3,4) puoi farlo facilmente applicando la formula (n * (n + 1)) / 2 dove n è l'ultimo numero


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

Questo codice rimuove il tuo sistema operativo? O mi invia le tue informazioni personali?

2

Questo è molto più semplice

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

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

console.log(sum)

2

Un semplice esempio di metodo:

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]));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.