web-dev-qa-db-fra.com

La sommation JavaScript la plus rapide

Quel est le moyen le plus rapide de résumer un tableau en JavaScript? Une recherche rapide retourne quelques méthodes différentes , mais j'aimerais une solution native si possible. Cela fonctionnera sous SpiderMonkey. 

Penser très à l'intérieur de la boîte que j'ai utilisé:

var count = 0;
for(var i = 0; i < array.length; i++)
{
    count = count + array[i];
}

Je suis sûr qu'il existe un meilleur moyen que l'itération directe. 

60
Josh K

Vous devriez pouvoir utiliser reduce.

var sum = array.reduce(function(pv, cv) { return pv + cv; }, 0);

La source

Et avec les fonctions de flèche introduites dans ES6, c'est encore plus simple:

sum = array.reduce((pv, cv) => pv+cv, 0);
115
ChaosPandion

Améliorations


Votre structure en boucle pourrait être faite plus rapidement:


   var count = 0;
   for(var i=0, n=array.length; i < n; i++) 
   { 
      count += array[i]; 
   }

Cela récupère array.length une fois, plutôt qu'à chaque itération. L'optimisation est faite en mettant en cache la valeur.


Si vous voulez vraiment accélérer les choses:


   var count=0;
   for (var i=array.length; i--;) {
     count+=array[i];
   }

Cela équivaut à une boucle while while. Il met en cache la valeur et est comparé à 0, donc une itération plus rapide.

Pour une liste de comparaison plus complète, voir mon JSFiddle.
Remarque: array.reduce est horrible ici, mais dans Firebug Console, il est le plus rapide.


Comparer les structures

J'ai commencé un JSPerf pour les sommations de tableaux. Il a été rapidement construit et il n’est pas garanti qu’il soit complet ou précis, mais c’est pour cela que edit

30
vol7ron

En cherchant la meilleure méthode pour résumer un tableau, j'ai écrit un test de performance.

Dans Chrome, "réduire" semble être largement supérieur

J'espère que ça aide

// Performance test, sum of an array
  var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  var result = 0;
// Eval
  console.time("eval");
  for(var i = 0; i < 10000; i++) eval("result = (" + array.join("+") + ")");
  console.timeEnd("eval");
// Loop
  console.time("loop");
  for(var i = 0; i < 10000; i++){
    result = 0;
    for(var j = 0; j < array.length; j++){
      result += parseInt(array[j]);
    }
  }
  console.timeEnd("loop");
// Reduce
  console.time("reduce");
  for(var i = 0; i < 10000; i++) result = array.reduce(function(pv, cv) { return pv + parseInt(cv); }, 0);
  console.timeEnd("reduce");
// While
  console.time("while");
  for(var i = 0; i < 10000; i++){
    j = array.length;
    result = 0;
    while(j--) result += array[i];
  }
  console.timeEnd("while");

eval: 5233.000ms

boucle: 255.000ms

réduire: 70.000ms

pendant: 214.000ms

19
Inkh Su Tesou

La boucle la plus rapide, selon ce test est une boucle while en sens inverse

var i = arr.length; while (i--) { }

Donc, ce code pourrait être le plus rapide que vous puissiez obtenir

Array.prototype.sum = function () {
    var total = 0;
    var i = this.length; 

    while (i--) {
        total += this[i];
    }

    return total;
}

Array.prototype.sum ajoute une méthode sum à la classe array ... vous pouvez facilement en faire une fonction d'assistance.

5
CaffGeek

Ou vous pourriez le faire de la mauvaise façon.

var a = [1,2,3,4,5,6,7,8,9];

sum = eval(a.join("+"));

;)

3
Kodejuice

Pour votre cas spécifique, utilisez simplement la méthode reduce de Arrays:

var sumArray = function() {
    // Use one adding function rather than create a new one each
    // time sumArray is called
    function add(a, b) {
        return a + b;
    }

    return function(arr) {
        return arr.reduce(add);
    };
}();

alert( sumArray([2, 3, 4]) );
2
Tim Down

Basé sur ce test (pour-contre-pour-chaque-vs-réduire) et ceci (boucles)

Je peux dire que:

1 # le plus rapide: pour la boucle

var total = 0;

for (var i = 0, n = array.length; i < n; ++i)
{
    total += array[i];
}

2 # agrégé

Dans votre cas, vous n'en aurez pas besoin, mais cela vous apportera beaucoup de souplesse.

Array.prototype.Aggregate = function(fn) {
    var current
        , length = this.length;

    if (length == 0) throw "Reduce of empty array with no initial value";

    current = this[0];

    for (var i = 1; i < length; ++i)
    {
        current = fn(current, this[i]);
    }

    return current;
};

Usage:

var total = array.Aggregate(function(a,b){ return a + b });

Méthodes non concluantes

Viennent ensuite forEach et reduce qui ont presque les mêmes performances et varient d’un navigateur à l’autre, mais ils ont de toute façon les pires performances.

1
BrunoLM

Qu'en est-il de sommer les deux extrémités? Cela réduirait le temps de moitié. Ainsi:

1, 2, 3, 4, 5, 6, 7, 8; somme = 0

2, 3, 4, 5, 6, 7; somme = 10

3, 4, 5, 6; somme = 19

4, 5; somme = 28

somme = 37

Un algorithme pourrait être:

function sum_array(arr){
    let sum = 0,
        length = arr.length,
        half = Math.floor(length/2)

    for (i = 0; i < half; i++) {
        sum += arr[i] + arr[length - 1 - i]
    }
    if (length%2){
        sum += arr[half]
    }
    return sum
}

Il fonctionne plus rapidement lorsque je le teste sur le navigateur avec performance.now(). Je pense que c'est un meilleur moyen. Qu'en pensez-vous?

0
cesarvargas

l’un des plus simples, des plus rapides, des plus réutilisables et des plus flexibles est:

Array.prototype.sum = function () {
    for(var total = 0,l=this.length;l--;total+=this[l]); return total;
}

// usage
var array = [1,2,3,4,5,6,7,8,9,10];
array.sum()
0
espiralis