Comment trouver la somme d'un tableau de nombres


810

Étant donné un tableau [1, 2, 3, 4], comment puis-je trouver la somme de ses éléments? (Dans ce cas, la somme serait 10.)

J'ai pensé que cela $.eachpourrait être utile, mais je ne sais pas comment le mettre en œuvre.


4
Cette question fait l'objet d'une méta-discussion
Madara's Ghost

19
@ tereško Le refus de google n'est pas une raison valable valable sur Stackoverflow. S'il vous plaît, votez si vous pensez que la question n'est pas bien (re) recherchée. (A en juger également par les réponses - cela semble être un sujet très controversé avec de nombreuses solutions possibles, y compris certaines mauvaises pratiques très appréciées (eval) - de manière surprenante.)
Trilarion

8
Remarque: la plupart des réponses ici calculent essentiellement a[0] + a[1] + ..., ce qui peut se transformer en concaténation de chaînes si le tableau a des éléments non numériques. Par exemple ['foo', 42].reduce((a,b)=>a+b, 0) === "0foo42".
Beni Cherniavsky-Paskin

Aucun réducteur intégré ne pourrait alimenter Array.reduce? Penser quelque chose comme [1,2,3].reduce(Math.sum).
Phil

Réponses:


545

Recommandé (réduire avec la valeur par défaut)

Array.prototype.reduce peut être utilisé pour parcourir le tableau, en ajoutant la valeur d'élément actuelle à la somme des valeurs d'élément précédentes.

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

Sans valeur par défaut

Vous obtenez une TypeError

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

Avant les fonctions fléchées d'ES6

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

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

Entrées non numériques

Si des non-nombres sont des entrées possibles, vous voudrez peut-être gérer cela?

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

Utilisation dangereuse de l' évaluateur non recommandée

Nous pouvons utiliser eval pour exécuter une représentation sous forme de chaîne de code JavaScript. En utilisant la fonction Array.prototype.join pour convertir le tableau en chaîne, nous changeons [1,2,3] en "1 + 2 + 3", ce qui donne 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('+'))

Bien sûr, afficher une alerte n'est pas la pire chose qui puisse arriver. La seule raison pour laquelle j'ai inclus ceci est comme une réponse à la question d'Ortund car je ne pense pas qu'elle ait été clarifiée.


8
Vous savez que cette magie reduce()est toujours 25-30% plus lente qu'une simple for()boucle indexée après de longues années? jsperf.com/reduce-vs-loop/4
tevemadar

Cela pose des problèmes si le nombre est "0" d'ailleurs - il peut être interprété comme la chaîne, pour une raison quelconque. Ajouter 1 * a + 1 * b a fonctionné pour moi. Quant à la vitesse, c'était plus facile à écrire et je m'en fiche de la vitesse
Peter Kay

1179

À Lisp , ce serait exactement le travail pour reduce. Vous verriez ce type de code:

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

Heureusement, en JavaScript, nous en avons aussi reduce! Malheureusement, +c'est un opérateur, pas une fonction. Mais nous pouvons le rendre joli! Ici, regardez:

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

N'est-ce pas joli? :-)

Encore mieux! Si vous utilisez ECMAScript 2015 (alias ECMAScript 6 ), cela peut être assez joli:

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

28
En supposant que nous utilisons tous ES2015, nous pouvons le rendre moins verbeux:[1, 2, 3].reduce((a,b)=>a+b)
Denys Séguret

1
Je me demande si le temps d'exécution de réduire avec une fonction (a, b) est comparable à une itération et une sommation manuelles ou s'il y a une surcharge considérable incluse?
Trilarion

1
Je pense qu'il vaut la peine de mentionner que la réponse peut être trouvée sur la page que vous avez liée: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Alex Cohn

2
J'ajouterais quelques méthodes à Array: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, il réduit un tableau en une seule valeur.
Florian Margaine

205

Pourquoi ne pas réduire? C'est généralement un peu contre-intuitif, mais l'utiliser pour trouver une somme est assez simple:

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

3
IE8 ne le prend pas en charge et il ne semble pas que jQuery ait l'intention de l'ajouter. Cependant, Prototype l'a.
Ishmael Smyrnow

4
@Ishmael, vous pouvez utiliser UnderscoreJS, qui revient à l'implémentation du navigateur si disponible, ou implémente le sien autrement.
Pablo Diaz

3
Qu'est-ce qui est contre-intuitif reduce()?
canon

3
@ s4nji Array.prototype.reduce() réduit un tableau à une seule valeur de retour.
canon

6
@ s4nji ... sauf si vous réduisez une sauce - auquel cas vous la réduisez à l'essentiel, c'est-à-dire la somme de toutes les saveurs sans l'eau au-dessus. :-)
CB Du Rietz

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

3
C'est bien plus rapide que la solution jQuery.each () ci-dessus.
Angry Dan

41
@Sprog: Cependant, l'utilisation (var i=0; i<arr.length; i++)est encore plus rapide. Et même alors, l'utilisation var sum=0; var i=arr.length; while(i--) sum += arr[i]est encore plus rapide.
Riking

14
L'utilisation de for... inboucles sur les tableaux fonctionne dans ce cas _ par coïncidence_ et parce que les tableaux étendent les objets. La solution de Riking est meilleure
Benjamin Gruenbaum

2
@BenjaminGruenbaum a fourni que rien n'a ajouté des propriétés énumérables au prototype du tableau ...
canon

1
@YSC non, ce n'est pas le cas. Une for...inboucle en JavaScript prend les indices, ce qui est une pierre d'achoppement courante pour les codeurs qui s'attendent à obtenir les valeurs. (Essayez for(var i in [1,2,3]) { console.log(i); }dans une console.)
Ambre

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

87
S'il vous plaît, s'il vous plaît, veuillez utiliser la réponse reduceci-dessous; ne déclarez pas de variables mutables lorsque vous n'en avez pas trop.
Bruno Grieder

9
Cette réponse fait l'objet d'une méta-discussion
Madara's Ghost

11
Veuillez ne pas l'utiliser, même s'il s'agit de la "réponse acceptée"; la réponse de Florian ci-dessous est bien meilleure!
Andy Sinclair

12
@BrunoGrieder "Ne déclarez pas les vars mutables quand vous n'y êtes pas obligé" est une opinion extrêmement biaisée sur un langage impératif , ce n'est guère une odeur de code par un effort d'imagination. Il n'y a absolument rien de mal à la réponse de Tyler, et la seule différence entre Tyler et Florian est le style.
Rob

5
De OP: Je pensais que $ .each pourrait être utile, mais je ne sais pas comment l'implémenter. Ce n'est peut-être pas le meilleur, mais répondez à la demande du PO.


29

Cela est possible en bouclant sur tous les éléments et en les ajoutant à chaque itération à une sumvariable.

var array = [1, 2, 3];

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

JavaScript ne connaît pas la portée des blocs, il sumsera donc accessible:

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

Le même que ci-dessus, cependant annoté et préparé comme une fonction 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;
}

12
Bien qu'intelligent, je trouverais le code déclarant en sumdehors de la boucle beaucoup plus lisible.
Beni Cherniavsky-Paskin

@ BeniCherniavsky-Paskin Ouais, pareil ici ... Je ne sais pas pourquoi je l'ai fait de cette façon ce jour-là ... Cependant, je vais le laisser tel quel! C'est juste un exemple de la façon dont nous pourrions peut-être ... ;)
yckart

Depuis ES6, javascript connaît la portée des blocs avec constet let. Vous pouvez donc déclarer en sumdehors de la forboucle comme let sum = 0;. Vous pouvez également mettre en cache la longueur du tableau avant la boucle commeconst length = array.length;
KSK

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

Référence: Array.prototype.reduce ()


6
Cela échouera si arrc'est le cas [].

7
Ajoutez une valeur par défaut, comme ceci: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];

Cela prendra en moyenne 1,57 ms / run (mesuré sur 1000 runs sur un tableau de 100 nombres normaux aléatoires), contre 3,604 ms / run avec la eval()méthode ci-dessus et 2,151 ms / run avec un standard pour (i, length, ++ ) boucle.

Remarque sur la méthodologie: ce test a été exécuté sur un serveur de script Google Apps, de sorte que leurs moteurs javascript sont à peu près les mêmes que Chrome.

EDIT: --iau lieu d' i--enregistrer 0,12 ms à chaque exécution (i-- est 1,7)

EDIT: Holy expletive, peu importe tout ce post. Utilisez la méthode Reduce () mentionnée ci-dessus, c'est seulement 1 ms / run.


1
J'adore les timings que vous avez utilisés. Votre réponse ne dit pas seulement "Choisissez-moi, je suis meilleur!" Cela nous montre plutôt pourquoi . Quoi qu'il en soit, cela while (--i) do_somethingpourrait aussi fonctionner pour d'autres choses.
Redwolf Programs

var sum = arr[0]
noobninja

12

Vous pouvez également utiliser ReduceRight.

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

ce qui donne une sortie de 21.

Référence: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/ReduceRight


Devrait être plus rapide dans Chrome car l'optimisation du bouclage javascript (c'est-à-dire la décrémentation de la longueur) peut également être appliquée à l'assembly sous-jacent pour le faire fonctionner plus rapidement.
Jack Giffin

12

Quelqu'un à la recherche d'un oneliner fonctionnel comme moi? Prends ça:

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

Vous pouvez ajouter une valeur initiale pour réduire comme 2e arr.reduce(function(a, b) { return a + b;}, 0);
paramètre

Merci! je vais incorporer cela.
geek-merlin

12

OK, imaginez que vous avez ce tableau ci-dessous:

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

Commençons à chercher de nombreuses façons de le faire car je n'ai trouvé aucune réponse complète ici:

1) Utilisation de la réduction intégrée ()

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

2) Utilisation de la boucle 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) Utilisation de la boucle while

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

4) Utilisation de array forEach

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

et appelez-le comme ceci:

total(arr); //return 10

Il n'est pas recommandé de prototyper quelque chose comme ça à Array ...


11

Approche amusante:

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

5
Pourriez-vous développer cette réponse en expliquant ce qui se passe dans ce code? Pourquoi ça marche? Que fait-il exactement? Ces choses aident à améliorer la qualité de la réponse.
Ortund

@ user40521 a déjà répondu à cela comme je le pense. Je ne l'ai pas vu.
électron

Bien que cela soit court et doux, et certainement intéressant, il est également très inefficace. L'utilisation reduceest certainement préférable pour la majorité, sinon la totalité, des cas.
Ninjakannon

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

Je reçois donc en NaNessayant une eval(['alert("removing your computer")',2,3].join("+"))mauvaise réponse 0/10
pie6k

10

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

Cela fonctionne pour moi (le résultat devrait être 5). J'espère qu'il n'y a aucun inconvénient caché dans ce type de solution.


1
De plus, n'importe quel programmeur C ou Java pourrait comprendre cela.
Audrius Meskauskas

dans le simple but de résumer toutes les valeurs, la simple boucle simple old for n'a pas de rivaux en termes de temps d'exécution
fedeghe

Seul problème, c'est un peu ennuyeux quand vous avez 20 boucles pour toutes imbriquées les unes dans les autres
Redwolf Programs

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

De cette façon, vous pouvez mettre toutes sortes de choses exotiques dans le tableau.

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

Je ne plaisante qu'à moitié.


26
Je
rigole à

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

7

Je suis un débutant avec JavaScript et le codage en général, mais j'ai trouvé qu'un moyen simple et facile de additionner les nombres dans un tableau est comme ceci:

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

Fondamentalement, je voulais y contribuer car je n'ai pas vu beaucoup de solutions qui n'utilisent pas de fonctions intégrées, et cette méthode est facile à écrire et à comprendre.


1
En quoi est-ce différent de cette réponse de 2012 ou de cette réponse de 2014 ? Il y a deux solutions que vous n'avez pas vues.
Dan Dascalescu

5

Un court morceau de code JavaScript ferait ce travail:

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

Quelques personnes ont suggéré d'ajouter une .sum()méthode au Array.prototype. Ceci est généralement considéré comme une mauvaise pratique, donc je ne suggère pas que vous le fassiez.

Si vous insistez toujours pour le faire, voici une façon succincte de l'écrire:

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

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

Notez que la fonction ajoutée au prototype utilise un mélange de fonctions ES5 et ES6 et de syntaxe de flèche. Le functionest déclaré pour permettre à la méthode d'extraire le thiscontexte de celui sur Arraylequel vous travaillez. J'ai utilisé =>pour plus de concision dans l' reduceappel.


5

Utilisez une forboucle:

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

Ou même une forEachboucle:

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

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

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

Pour plus de simplicité, utilisez 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

Pas besoin initial value! Parce que si non initial valueest passé, le callback functionn'est pas invoqué sur le premier élément de la liste, et le premier élément est plutôt passé en tant que initial value. Très c OO l fonctionnalité :)

[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

Voici une élégante solution à une ligne qui utilise un algorithme de pile , bien que l'on puisse prendre un certain temps pour comprendre la beauté de cette implémentation.

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

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

Fondamentalement, la fonction accepte un tableau et vérifie si le tableau contient exactement un élément. S'il est faux, il fait sortir le dernier élément de la pile et renvoie le tableau mis à jour.

La beauté de cet extrait est que la fonction inclut une arr[0]vérification pour éviter une boucle infinie. Une fois qu'il a atteint le dernier élément, il retourne la somme entière.


4

Vous pouvez combiner la méthode Reduce () avec l'expression lambda:

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


3

j'ai vu toutes les réponses pour la solution «réduire»

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

3

Précision

Tableau de tri et somme de début sous forme de plus petits nombres (l'extrait de code montre la différence avec le non tri)

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

Pour un tableau multidimensionnel de nombres, utilisez arr.flat(Infinity)


2

Trucs sympas ici, j'ai un choix avec beaucoup de réponses traditionnelles sûres ne mettant pas en cache la longueur du tableau.

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

Sans mettre en cache la longueur du tableau, le compilateur JS doit parcourir le tableau à chaque itération de la boucle pour calculer la longueur, c'est une surcharge inutile dans la plupart des cas. La V8 et de nombreux navigateurs modernes optimisent cela pour nous, c'est donc moins un problème que par le passé, mais il existe des appareils plus anciens qui bénéficient de cette mise en cache simple.

Si la longueur est sujette à changement, la mise en cache peut provoquer des effets secondaires inattendus si vous ne savez pas pourquoi vous mettez en cache la longueur, mais pour une fonction réutilisable, le seul but est de prendre un tableau et d'ajouter les valeurs ensemble, c'est un grand ajustement.

Voici un lien CodePen pour cette fonction arraySum. http://codepen.io/brandonbrule/pen/ZGEJyV

Il est possible que ce soit un état d'esprit dépassé qui m'est resté, mais je ne vois aucun inconvénient à l'utiliser dans ce contexte.


Le problème de la mise en cache de la longueur est un hareng rouge. Les moteurs JS optimiseront cela pour vous sans clignoter.

2

Ce sont vraiment d'excellentes réponses, mais juste au cas où si les nombres sont dans l'ordre comme dans la question (1,2,3,4), vous pouvez facilement le faire en appliquant la formule (n * (n + 1)) / 2 où n est le dernier nombre


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

Ce code supprime-t-il votre système d'exploitation? Ou m'envoie-t-il vos informations personnelles?

2

C'est beaucoup plus facile

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 exemple de méthode 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]));
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.