So finden Sie die Summe eines Arrays von Zahlen

808

[1, 2, 3, 4]Wie kann ich bei einem Array die Summe seiner Elemente finden? (In diesem Fall wäre die Summe 10.)

Ich dachte, es $.eachkönnte nützlich sein, bin mir aber nicht sicher, wie ich es implementieren soll.

akano1
quelle
4
Diese Frage wird derzeit diskutiert
Madaras Geist
18
@ tereško Die Unwilligkeit gegenüber Google ist kein gültiger enger Grund für Stackoverflow. Bitte stimmen Sie ab, wenn Sie der Meinung sind, dass die Frage nicht gut (erneut) gesucht wird. (Auch nach den Antworten zu urteilen - dies scheint ein sehr kontroverses Thema mit vielen möglichen Lösungen zu sein, einschließlich einiger hoch bewerteter schlechter Praktiken (Bewertung) - überraschenderweise.)
Trilarion
8
Hinweis: Die meisten Antworten hier berechnen im Wesentlichen a[0] + a[1] + ..., was zu einer Verkettung von Zeichenfolgen führen kann, wenn das Array nicht nummerierte Elemente enthält. ZB ['foo', 42].reduce((a,b)=>a+b, 0) === "0foo42".
Beni Cherniavsky-Paskin
Kein eingebauter Reduzierer, den man Array.reduce zuführen könnte? Ich denke so etwas wie [1,2,3].reduce(Math.sum).
Phil

Antworten:

544

Empfohlen (mit Standardwert reduzieren)

Array.prototype.reduce kann verwendet werden, um das Array zu durchlaufen und den aktuellen Elementwert zur Summe der vorherigen Elementwerte hinzuzufügen.

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

Ohne Standardwert

Sie erhalten einen TypeError

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

Vor den Pfeilfunktionen von ES6

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

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

Nicht nummerierte Eingänge

Wenn Nicht-Zahlen mögliche Eingaben sind, möchten Sie vielleicht damit umgehen?

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

Nicht empfohlene gefährliche Bewertung

Wir können eval verwenden , um eine Zeichenfolgendarstellung von JavaScript-Code auszuführen. Mit der Funktion Array.prototype.join zum Konvertieren des Arrays in einen String ändern wir [1,2,3] in "1 + 2 + 3", was 6 ergibt.

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('+'))

Das Anzeigen einer Warnung ist natürlich nicht das Schlimmste, was passieren kann. Der einzige Grund, warum ich dies aufgenommen habe, ist die Beantwortung von Ortunds Frage, da ich nicht glaube, dass sie geklärt wurde.

OwChallie
quelle
8
Sie wissen, dass diese Magie mit nach langen Jahren reduce()immer noch 25-30% langsamer ist als eine einfache indizierte for()Schleife? jsperf.com/reduce-vs-loop/4
tevemadar
Dies stößt übrigens auf Probleme, wenn die Zahl "0" ist - sie kann aus irgendeinem Grund als Zeichenfolge interpretiert werden. Das Hinzufügen von 1 * a + 1 * b hat bei mir funktioniert. Was die Geschwindigkeit angeht, war dies einfacher zu schreiben und mir ist die Geschwindigkeit egal
Peter Kay
1179

In Lisp wäre dies genau der richtige Job reduce. Sie würden diese Art von Code sehen:

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

Zum Glück haben wir in JavaScript auch reduce! Leider +ist ein Operator keine Funktion. Aber wir können es hübsch machen! Hier, schau:

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

Ist das nicht hübsch? :-)

Noch besser! Wenn Sie ECMAScript 2015 (auch bekannt als ECMAScript 6 ) verwenden, kann dies so hübsch sein:

const sum = [1, 2, 3].reduce((partial_sum, a) => partial_sum + a,0); 
console.log(sum); // 6
Florian Margaine
quelle
28
Angenommen, wir alle verwenden ES2015, können wir es weniger ausführlich machen:[1, 2, 3].reduce((a,b)=>a+b)
Denys Séguret
1
Ich frage mich, ob die Ausführungszeit von Reduzieren mit einer Funktion (a, b) mit einer manuellen Iteration und Summierung vergleichbar ist oder ob ein erheblicher Overhead enthalten ist.
Trilarion
1
Ich glaube, es ist erwähnenswert, dass die Antwort tatsächlich auf der Seite zu finden ist, die Sie verlinkt haben: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Alex Cohn
2
Ich würde Array einige Methoden hinzufügen: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 reduziert ein Array auf einen einzigen Wert.
Florian Margaine
205

Warum nicht reduzieren? Es ist normalerweise etwas kontraintuitiv, aber es ist ziemlich einfach, es zu verwenden, um eine Summe zu finden:

var a = [1,2,3];
var sum = a.reduce(function(a, b) { return a + b; }, 0);
Casey Rodarmor
quelle
3
IE8 unterstützt es nicht und es sieht nicht so aus, als ob jQuery beabsichtigt, es hinzuzufügen. Prototype hat es jedoch.
Ishmael Smyrnow
4
@Ishmael, Sie können UnderscoreJS verwenden, das auf die Implementierung des Browsers zurückgreift, sofern verfügbar, oder auf andere Weise implementiert.
Pablo Diaz
3
Was ist kontraintuitiv reduce()?
Kanon
3
@ s4nji Array.prototype.reduce() reduziert ein Array auf einen einzelnen Rückgabewert.
Kanon
6
@ s4nji ... es sei denn, Sie reduzieren eine Sauce - in diesem Fall reduzieren Sie sie auf das Wesentliche, dh die Summe aller Aromen ohne das Wasser über dem Kopf. :-)
CB Du Rietz
97
var arr = [1,2,3,4];
var total=0;
for(var i in arr) { total += arr[i]; }
Bernstein
quelle
3
Dies ist viel schneller als die obige Lösung jQuery.each ().
Dan
41
@Sprog: Die Verwendung (var i=0; i<arr.length; i++)ist jedoch noch schneller. Und selbst dann ist die Verwendung var sum=0; var i=arr.length; while(i--) sum += arr[i]noch schneller.
Riking
14
Die Verwendung von for... inSchleifen für Arrays funktioniert in diesem Fall zufällig und weil Arrays Objekte erweitern. Rikings Lösung ist besser
Benjamin Gruenbaum
2
@BenjaminGruenbaum vorausgesetzt, dass nichts dem Prototyp des Arrays unzählige Eigenschaften hinzugefügt hat ...
Canon
1
@YSC nein, das tut es nicht. Eine for...inSchleife in JavaScript nimmt die Indizes auf, was ein häufiger Stolperstein für Codierer ist, die erwarten, die Werte zu erhalten. (Versuchen Sie es for(var i in [1,2,3]) { console.log(i); }in einer Konsole.)
Amber
61
var total = 0;
$.each(arr,function() {
    total += this;
});
Tyler Carter
quelle
87
Bitte, bitte, bitte benutze die Antwort mit reduceunten; Deklarieren Sie keine veränderlichen Variablen, wenn Sie keine haben.
Bruno Grieder
9
Diese Antwort wird derzeit diskutiert
Madaras Geist
11
Bitte verwenden Sie dies nicht, obwohl es die "akzeptierte Antwort" ist; Die Antwort von Florian unten ist viel besser!
Andy Sinclair
12
@BrunoGrieder "Deklariere keine veränderlichen Vars, wenn du nicht musst" ist eine extrem voreingenommene Meinung über eine imperative Sprache , es ist kaum ein Code-Geruch in irgendeiner Weise. An Tylers Antwort ist absolut nichts auszusetzen, und der einzige Unterschied zwischen Tylers und Florians ist der Stil.
Rob
5
Von OP: Ich dachte, $ .each könnte nützlich sein, bin mir aber nicht sicher, wie ich es implementieren soll. Dies ist vielleicht nicht die beste, aber beantworten Sie die Anfrage des OP.
33

Wenn Sie zufällig Lodash verwenden, können Sie die Summenfunktion verwenden

array = [1, 2, 3, 4];
sum = _.sum(array); // sum == 10
David sagt Reinstate Monica
quelle
29

Dies ist möglich, indem alle Elemente sumdurchlaufen und bei jeder Iteration zu einer Variablen hinzugefügt werden.

var array = [1, 2, 3];

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

JavaScript kennt das Block-Scoping nicht und ist daher sumzugänglich:

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

Das gleiche wie oben, jedoch als einfache Funktion kommentiert und vorbereitet:

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
quelle
12
Obwohl klug, würde ich Code, der sumaußerhalb der Schleife deklariert , viel besser lesbar finden.
Beni Cherniavsky-Paskin
@ BeniCherniavsky-Paskin Ja, das gleiche hier ... Ich weiß nicht, warum ich es an diesem Tag so gemacht habe ... Aber ich werde es so lassen, wie es ist! Es ist nur ein Beispiel, wie wir könnten ... ;)
Yckart
Seit ES6 kennt Javascript Block Scoping mit constund let. Sie können also sumaußerhalb der forSchleife als deklarieren let sum = 0;. Sie können die Array-Länge auch vor der Schleife alsconst length = array.length;
KSK
23
arr.reduce(function (a, b) {
    return a + b;
});

Referenz: Array.prototype.reduce ()

onhout
quelle
6
Dies wird fehlschlagen, wenn dies der Fall arrist [].
7
Fügen Sie einen Standardwert hinzu, wie arr.reduce(function (a, b) { return a + b; }, 0);
folgt
15
// Given array 'arr'
var i = arr.length;
var sum = 0;
while (--i) sum += arr[i];

Dies dauert durchschnittlich 1,57 ms / Lauf (gemessen über 1000 Läufe auf einem Array von 100 zufälligen Normalzahlen), verglichen mit 3,604 ms / Lauf mit der eval()obigen Methode und 2,151 ms / Lauf mit einem Standard für (i, Länge, ++) ) Schleife.

Hinweis zur Methodik: Dieser Test wurde auf einem Google Apps Script-Server ausgeführt, sodass die Javascript-Engines weitgehend mit denen von Chrome identisch sind.

BEARBEITEN: --ianstatt i--0,12 ms pro Lauf zu speichern (i-- ist 1,7)

EDIT: Holy Expletive, egal diesen ganzen Beitrag. Verwenden Sie die oben erwähnte Methode redu (), sie beträgt nur 1 ms / Lauf.

Riking
quelle
1
Ich liebe die Timings, die du benutzt hast. Ihre Antwort lautet nicht nur "Such mich aus, ich bin der Beste!" Es zeigt uns stattdessen warum . Wie auch immer, das while (--i) do_somethingkönnte auch für andere Dinge funktionieren.
Redwolf Programme
var sum = arr[0]
Noobninja
12

Sie können auch reduRight verwenden.

[1,2,3,4,5,6].reduceRight(function(a,b){return a+b;})

was ergibt Ausgabe als 21.

Referenz: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/ReduceRight

Rohit Bhalke
quelle
Sollte in Chrome schneller sein, da die Optimierung auf Javascript-Schleifen (dh das Verringern der Länge) auch auf die zugrunde liegende Assembly angewendet werden kann, um deren Ausführung zu beschleunigen.
Jack Giffin
12

Wer sucht einen funktionierenden Oneliner wie mich? Nimm das:

sum= arr.reduce(function (a, b) {return a + b;}, 0);
Geek-Merlin
quelle
Sie können einen Anfangswert für Reduzieren als 2. Parameter hinzufügen:arr.reduce(function(a, b) { return a + b;}, 0);
Ngz
Vielen Dank! Ich werde das einbauen.
Geek-Merlin
12

Lustiger Ansatz:

eval([1,2,3].join("+"))
Elektron
quelle
5
Könnten Sie diese Antwort bitte erweitern, indem Sie erklären, was in diesem Code passiert? Warum funktioniert es? Was macht es genau? Diese Dinge tragen dazu bei, die Qualität der Antwort zu verbessern.
Ortund
@ user40521 hat dies bereits so beantwortet, wie ich denke. Ich habe es nicht gesehen.
Elektron
Dies ist zwar kurz und bündig und sicherlich interessant, aber auch sehr ineffizient. Die Verwendung reduceist in den meisten, wenn nicht allen Fällen definitiv vorzuziehen.
Ninjakannon
Errm,[1,"2;YourProgram.ripToShreds();3",4]
Redwolf Programme
Also bekomme ich NaNbeim Versuch eine eval(['alert("removing your computer")',2,3].join("+"))falsche Antwort 0/10
pie6k
12

OK, stellen Sie sich vor, Sie haben dieses Array unten:

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

Lassen Sie uns viele verschiedene Möglichkeiten untersuchen , da ich hier keine umfassende Antwort finden konnte:

1) Verwenden der integrierten Reduktion ()

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

2) Verwenden der for-Schleife

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) Verwenden der while-Schleife

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

4) Verwenden des Arrays forEach

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

und nenne es so:

total(arr); //return 10

Es wird nicht empfohlen, einen solchen Prototyp für Array zu erstellen ...

Alireza
quelle
10

Eine Standard-JavaScript-Lösung:

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

Das funktioniert bei mir (das Ergebnis sollte 5 sein). Ich hoffe, dass diese Art von Lösung keinen versteckten Nachteil hat.

Nano
quelle
1
Auch jeder C- oder Java-Programmierer könnte dies verstehen.
Audrius Meskauskas
Für den einfachen Zweck, alle Werte zusammenzufassen, hat die einfache einfache alte for-Schleife keine Rivalen in Bezug auf die Ausführungszeit
am
Das einzige Problem ist, es ist ein bisschen ärgerlich, wenn Sie 20 for-Schleifen haben, die alle ineinander verschachtelt sind
Redwolf Programs
7
var totally = eval(arr.join('+'))

Auf diese Weise können Sie alle Arten von exotischen Dingen in das Array aufnehmen.

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

Ich scherze nur halb.

user40521
quelle
26
Ich bin halb lachend
caub
eval(['alert("removing your computer")',2,3].join("+"))
Pie6k
7

Ich bin ein Anfänger mit JavaScript und Codierung im Allgemeinen, aber ich fand, dass eine einfache und einfache Möglichkeit, die Zahlen in einem Array zu summieren, folgendermaßen ist:

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

Grundsätzlich wollte ich dazu beitragen, weil ich nicht viele Lösungen gesehen habe, die keine integrierten Funktionen verwenden, und diese Methode ist einfach zu schreiben und zu verstehen.

CandyPaintedRIMS
quelle
1
Wie unterscheidet sich das von dieser Antwort von 2012 oder dieser Antwort von 2014 ? Es gibt zwei Lösungen, die Sie nicht gesehen haben.
Dan Dascalescu
5

Ein kurzes Stück JavaScript-Code würde diesen Job erledigen:

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
quelle
5

Einige Leute haben vorgeschlagen, eine .sum()Methode zum hinzuzufügen Array.prototype. Dies wird im Allgemeinen als schlechte Praxis angesehen, daher schlage ich nicht vor, dass Sie es tun.

Wenn Sie immer noch darauf bestehen, ist dies eine prägnante Schreibweise:

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

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

Beachten Sie, dass die dem Prototyp hinzugefügte Funktion eine Mischung aus ES5- und ES6-Funktion und Pfeilsyntax verwendet. Das functionwird deklariert, damit die Methode den thisKontext von dem Arrayabrufen kann, mit dem Sie arbeiten. Ich habe das der =>Kürze halber innerhalb des reduceAnrufs verwendet.

Kerl
quelle
5

Verwenden Sie eine forSchleife:

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

Oder sogar eine forEachSchleife:

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

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

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

Verwenden Sie zur Vereinfachung 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
quelle
4

Keine Notwendigkeit initial value! Denn wenn no übergeben initial valuewird, wird das callback functionnicht für das erste Element der Liste aufgerufen, und das erste Element wird stattdessen als übergeben initial value. Sehr gute Funktion :)

[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
Ja
quelle
4

Hier ist eine elegante Einzeilerlösung, die einen Stapelalgorithmus verwendet . Es kann jedoch einige Zeit dauern, bis Sie die Schönheit dieser Implementierung verstanden haben.

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

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

Grundsätzlich akzeptiert die Funktion ein Array und prüft, ob das Array genau ein Element enthält. Wenn false, wird das letzte Element aus dem Stapel entfernt und das aktualisierte Array zurückgegeben.

Das Schöne an diesem Snippet ist, dass die Funktion die arr[0]Überprüfung umfasst , um Endlosschleifen zu verhindern. Sobald das letzte Element erreicht ist, wird die gesamte Summe zurückgegeben.

Rex Low
quelle
4

Sie können die Methode redu () mit dem Lambda-Ausdruck kombinieren:

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

Verwenden reduce

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

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

console.log(sum);

Damien Asseya
quelle
3

Ich sah alle Antworten für "reduzieren" Lösung gehen

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
quelle
3

Richtigkeit

Sortieren Sie das Array und die Startsumme aus den kleinsten Zahlen (Snippet zeigt Unterschied zu Nicht-Sortierung)

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

Für mehrdimensionale Zahlenreihen verwenden arr.flat(Infinity)

Kamil Kiełczewski
quelle
2

Coole Tricks hier, ich habe eine gute Wahl mit vielen der sicheren traditionellen Antworten, die nicht die Länge des Arrays zwischenspeichern.

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

Ohne die Länge des Arrays zwischenzuspeichern, muss der JS-Compiler das Array bei jeder Iteration der Schleife durchlaufen, um die Länge zu berechnen. In den meisten Fällen ist dies kein unnötiger Overhead. V8 und viele moderne Browser optimieren dies für uns, daher ist dies weniger ein Problem als früher, aber es gibt ältere Geräte, die von diesem einfachen Caching profitieren.

Wenn sich die Länge ändern kann, kann das Zwischenspeichern zu unerwarteten Nebenwirkungen führen, wenn Sie nicht wissen, warum Sie die Länge zwischenspeichern. Bei einer wiederverwendbaren Funktion besteht der einzige Zweck darin, ein Array zu verwenden und die Werte zu addieren tolle Passform.

Hier ist ein CodePen-Link für diese arraySum-Funktion. http://codepen.io/brandonbrule/pen/ZGEJyV

Es ist möglich, dass dies eine veraltete Denkweise ist, die mir am Herzen liegt, aber ich sehe keinen Nachteil darin, sie in diesem Zusammenhang zu verwenden.

Brandon Brule
quelle
Das Problem des Zwischenspeicherns der Länge ist ein roter Hering. JS-Engines optimieren dies für Sie, ohne zu blinken.
2

Das sind wirklich gute Antworten, aber nur für den Fall, dass die Zahlen wie in der Frage (1,2,3,4) aufeinander folgen, können Sie dies leicht tun, indem Sie die Formel (n * (n + 1)) / 2 anwenden, wobei n ist die letzte Zahl

Santosh
quelle
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
quelle
Entfernt dieser Code Ihr Betriebssystem? Oder sendet es Ihre persönlichen Daten an mich?
2

Das ist viel einfacher

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
quelle
2

Ein einfaches Methodenbeispiel:

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
quelle