¿Cuál es la manera más rápida de resumir un array en JavaScript? Una rápida búsqueda se vuelve más un par de métodos diferentes, pero me gustaría una solución nativa, si es posible. Este se ejecutará en virtud de mono araña.

Pensando muy en el interior de la caja, he estado usando:

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

Estoy seguro de que hay una mejor manera, a continuación, directamente de la iteración.

  • La PRUEBA!!! Si usted necesita para ver cuál es la manera más rápida de hacer algo, probar varios, y medir los resultados.
  • Bueno, obviamente, sin embargo, yo no estoy en mi «fuera de la caja» pensamiento días.
InformationsquelleAutor Josh K | 2010-09-21

9 Comentarios

  1. 123

    Usted debería ser capaz de utilizar reduce.

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

    Fuente

    Y con flecha funciones introducido en ES6, es aún más sencillo:

    sum = array.reduce((pv, cv) => pv + cv, 0);
    • … excepto en IE <= 8.
    • De acuerdo a la documentación vinculada, «[reducir] puede no estar disponible en todos los navegadores»
    • De nuevo, este se está ejecutando bajo el mono araña, no cualquier navegador en particular.
    • Ah, lo siento, me perdí. En el que caso de que esta es la respuesta.
    • De alguna manera lo dudo, aunque reduce es una función nativa. En rendimiento orientada código JS, evitando las llamadas de función es casi siempre más rápido,
    • Desde mi experiencia, la sobrecarga de la función de llamadas en su mayoría proviene de los estados de mirar hacia arriba.
    • de la matriz.reducir es grande en la Consola de Firebug, pero es muy lento en otros navegadores cuando se compara con las otras soluciones (ver mi JSFiddle).
    • MooGoo: usted puede estar en lo cierto. Confieso que no me de la prueba y sólo supone el método nativo sería fatser.
    • Si desea utilizar reducir en IE <=8, el uso de Mozilla compatibilidad de cuña: developer.mozilla.org/en-US/docs/JavaScript/Reference/…
    • Array.reduce es muy lento en comparación con otros métodos. jsperf.com/array-reduce-vs-foreach/2
    • esto no es más cierto!

  2. 30

    Mejoras

    Su estructura de bucle podría hacerse más rápido:


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

    Esta forma, se recupera array.length vez, en lugar de con cada iteración. La optimización se realiza mediante el almacenamiento en caché el valor.

    Si usted realmente desea acelerar:


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

    Esto es equivalente a una mientras que la inversa de bucle. Almacena el valor de y es comparado con el 0, por lo tanto más rápido de la iteración.

    Para una información más completa lista de comparación, ver a mi JSFiddle.

    Nota: matriz.reducir es horrible que hay, pero en la Consola de Firebug es más rápido.


    Comparar Las Estructuras

    Empecé un JSPerf de una matriz de sumatorias. Rápidamente se construye y no se garantiza que sea completa o precisa, pero eso es lo que editar es para 🙂

    • Su for bucles son casi iguales. He probado y a veces se incremento de manera más rápida que disminuye. Y La Matriz.reducir es terriblemente lento. jsperf.com/array-reduce-vs-foreach/2
    • Algunos de bucle de prueba jsperf.com/loops/98
    • tienes razón, este es un viejo respuesta desde hace 3 años. Creo que poco después, hubo algunas nuevas JS motores disponibles y los motores existentes habían sido modificada de modo que hacia el bucle era más rápido que invertir tiempo. Esto va a demostrar por qué el micro-optimizaciones son generalmente mal aconsejado. Me gustaría seguir con la prueba y de referencia — jsperf es un gran sitio para hacerlo, si usted no tiene un local suite.
    • jsperf.com/loops/106 para una actualización
    • Preferido respuesta
    • Los enlaces de JS Violín tiene un error en «Bucle For: Longitud de almacenamiento en Caché (inversa)»‘. Siempre se agrega el elemento en el índice 0 para la suma. for (var i = 0, n = array.length; n > i; n--) { sum += array[i]; } debe ser cambiado a for (var i = 0, n = array.length-1; n >= i; n--) { sum += array[n]; }. Esto pone en el mismo estadio de béisbol como el otro almacenamiento en caché de los bucles.

  3. 20

    Mientras que la búsqueda por el mejor método de suma de una matriz, escribí una prueba de rendimiento.

    En Chrome, «reducir» parece ser muy superior

    Espero que esto ayude a

    //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.000 ms

    bucle: 255.000 ms

    reducir: 70.000 ms

    mientras: 214.000 ms

    • Gracias por esto, ¿por qué hay necesidad de ser un parseInt en la reducción de la función? He intentado y he necesitado en mi código.
    • Hmm, no estoy seguro, probarlo sin el parseInt .. esto lo escribí hace 4 años : D
  4. 5

    La forma más rápida de bucle, de acuerdo a esta prueba es un bucle while en el reverso

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

    Así, este código puede ser el más rápido usted puede conseguir

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

    Array.prototype.sum agrega una suma método a la clase array… que fácilmente podría hacer que una función auxiliar en su lugar.

    • Mi inversa es ligeramente más rápido, más veces de las que no.
    • muy, muy, muy marginalmente, estamos hablando de ~1ms más de 1000 registros
    • 🙂 sí sí y no todo el tiempo. aún así, estoy más propensos a utilizar for(var i=0,n=a.length;i<n;i++){} debido a que el inicio/parada de la estructura de control.
    • ¿De dónde arr provienen de la sum método? Debe arr realmente this?
    • sí, eso parece correcto.
    • Parece que mientras que la evaluación de la condición booleana hace más rápido jsperf.com/while-bool-vs-while
    • no parece ser fiable más rápido, he conseguido resultados drásticamente diferentes cada vez que lo ejecuto.

  5. 2

    Para su caso específico, sólo tiene que utilizar el reduce método de Matrices:

    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]) );
  6. 1

    Basado en esta prueba (para-vs-forEach-vs-reducir) y este (bucles)

    Puedo decir que:

    1# Rápido: bucle for

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

    2# Agregado

    Para usted en caso de que usted no necesita esto, sino que se añade una gran cantidad de flexibilidad.

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

    Uso:

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

    Concluyentes métodos

    Luego viene forEach y reduce que tienen casi el mismo rendimiento y varía de un navegador a otro, pero tienen el peor desempeño de todos modos.

  7. 0

    uno de los más simple, más rápido, más reutilizable y flexible es:

    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()
    • Lol! Esto no es ni simple, ni más rápido, ni más reutilizable, ni más flexible que la de reducir!
    • Este es sin duda el más rápido (ver jsben.ch/0Qa3G) y puede ser hecho de otra manera divertida de class UintArray extends Uint8Array { sum () { FUNCTION_CODE_HERE } }
    • El cambio de la matriz prototipo romper los bucles for..in!
  8. 0

    Lo que acerca de sumar ambas extremidades? Se reduciría a la mitad del tiempo. Así:

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

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

    3, 4, 5, 6; suma = 19

    4, 5; suma = 28

    suma = 37

    Un algoritmo puede ser:

    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
    }

    Se realiza más rápido cuando la pruebo en el navegador con performance.now().
    Creo que esta es una mejor manera. ¿Ustedes qué piensan?

    • Técnicamente en la Notación O O(n/2) es igual a O(n). Por qué? Porque lo que la estimación no es ¿es rápido para una entrada dada, pero ¿cómo hace el cambio de velocidad con el cambio de entrada. Si el doble de la entrada para un O(n) en función lleva el doble de tiempo. Si el doble de la entrada para un O(n/2) función lleva el doble de tiempo. Si el doble de la entrada para un O(n2) se toma cuatro veces más largo.
    • Estás en lo correcto. He editado mi respuesta.

Dejar respuesta

Please enter your comment!
Please enter your name here