¿Cuál es la forma más rápida de recorrer una matriz en JavaScript?

248

Aprendí de los libros que deberías escribir para un bucle como este:

for(var i=0, len=arr.length; i < len; i++){
    // blah blah
}

entonces el arr.length que no se calculará cada vez.

Otros dicen que el compilador hará alguna optimización para esto, por lo que puede escribir:

for(var i=0; i < arr.length; i++){
    // blah blah
}

Solo quiero saber cuál es la mejor manera en la práctica.

wong2
fuente
1
También vale la pena echarle un vistazo cuando se trata de bucles de matriz: jsperf.com/array-loop-var-caching
cloakedninjas
@ wong2 Este punto de referencia de Browserdiet tiene una colección más completa de alternativas.
Domi
1
jsben.ch/#/y3SpC
EscapeNetscape
Mejorado en el jsben anterior: jsben.ch/#/R6LbS
Corbfon
¿Podemos presentar el for ... ofciclo a esta competencia? La sintaxis parece aún más fácil que un bucle for sin almacenamiento en caché, y quiero saber si debo cambiar a usar for for loops.
programadorRaj

Respuestas:

339

Después de realizar esta prueba con la mayoría de los navegadores modernos ...

http://jsben.ch/dyM52

Actualmente , la forma más rápida de bucle (y en mi opinión, la más sintácticamente obvia).

un estándar para bucle con almacenamiento en caché de longitud

for (var i = 0, len = myArray.length; i < len; i++) {

}

Diría que este es definitivamente un caso donde aplaudo a los desarrolladores de motores de JavaScript. Un tiempo de ejecución debe optimizarse para mayor claridad , no inteligencia .

jondavidjohn
fuente
66
Curiosamente, en IE9 esto es más rápido: para (var i = 0, len = myArray.length; i <len; ++ i) {} // prefix incr, en lugar de postfix
Christopher Bennage
44
Consulte Preferir operadores de prefijo sobre postfix para conocer otros motivos ++i.
Bennett McElwee
44
Probé usando el operador de prefijo como sugirió @BennettMcElwee y se ejecuta un poco más rápido: for(var i=0, len=myArray.length; i<len; ++i) Verifique jsperf.com/caching-array-length/84
victmo
21
Tienes que tener cuidado al usar este bucle. Comencé a usarlo y tuve un error difícil de rastrear debido a un error que cometí. Si anidas dos bucles como este: jsfiddle.net/KQwmL/1 . Debe tener cuidado de nombrar la variable var de manera diferente en los dos bucles, de lo contrario el segundo bucle sobrescribirá la primera len.
Rui Marques
66
@WillshawMedia Puede declarar múltiples variables con una sola vardeclaración. La forma en que se escribe, en lenrealidad , tiene un alcance tal como lo sugiere.
jondavidjohn
90

La forma más rápida de recorrer una matriz de JavaScript es:

var len = arr.length;
while (len--) {
    // blah blah
}

Ver http://blogs.oracle.com/greimer/entry/best_way_to_code_a para una comparación completa

gnur
fuente
1
No olvides usar var(de lo contrario se lenconvierte en una variable global). Además, consulte jsperf.com/loops para obtener más puntos de referencia de bucles.
Mathias Bynens
22
La publicación de blog en la que se basa esta respuesta ahora tiene casi 4 años, y mucho ha cambiado en los motores js en ese momento, vea mi respuesta a continuación para obtener una comparación actualizada.
jondavidjohn
1
Estoy de acuerdo con @jondavidjohn. Probé este código y resultó ser el menos eficiente ... Verifique jsperf.com/caching-array-length/84
victmo el
La respuesta anterior es casi universalmente (en todos los navegadores) mucho más lenta que un ciclo for. Vea el enlace JSPerf en la respuesta aceptada. Es una gran pena, porque es extremadamente legible en mi opinión.
Letharion
3
Adivino @jondavidjohn que lo que quieres decir con 'mi respuesta a continuación' es 'mi respuesta arriba' jajaja.
Shanimal
40

A partir de junio de 2016 , realizando algunas pruebas en el último Chrome (71% del mercado de navegadores en mayo de 2016, y en aumento):

  • El bucle más rápido es un bucle for , con y sin longitud de almacenamiento en caché que ofrece un rendimiento realmente similar. (El bucle for con longitud en caché a veces arrojó mejores resultados que el que no tiene caché, pero la diferencia es casi insignificante, lo que significa que el motor ya podría estar optimizado para favorecer el bucle estándar y probablemente más directo sin caché).
  • El ciclo while con decrementos fue aproximadamente 1,5 veces más lento que el ciclo for.
  • Un bucle que utiliza una función de devolución de llamada (como el estándar para cada), fue aproximadamente 10 veces más lento que el bucle for.

Creo que este hilo es demasiado viejo y es engañoso para los programadores pensar que necesitan almacenar en caché la longitud, o usar recorridos inversos con decrementos para lograr un mejor rendimiento, escribir código que sea menos legible y más propenso a errores que un simple bucle directo. Por lo tanto, recomiendo:

  • Si su aplicación itera sobre muchos elementos o su código de bucle está dentro de una función que se usa con frecuencia, un bucle directo es la respuesta:

    for (var i = 0; i < arr.length; i++) {
      // Do stuff with arr[i] or i
    }
  • Si su aplicación realmente no recorre muchos elementos o solo necesita hacer pequeñas iteraciones aquí y allá, usar el estándar para cada devolución de llamada o cualquier función similar de su biblioteca JS de elección podría ser más comprensible y menos propenso a errores, ya que El alcance de la variable de índice está cerrado y no necesita usar corchetes, accediendo directamente al valor de la matriz:

    arr.forEach(function(value, index) {
      // Do stuff with value or index
    });
  • Si realmente necesita rascarse unos pocos milisegundos mientras itera sobre miles de millones de filas y la longitud de su matriz no cambia a través del proceso, puede considerar almacenar en caché la longitud en su bucle for. Aunque creo que esto realmente no es necesario hoy en día:

    for (var i = 0, len = arr.length; i < len; i++) {
      // Do stuff with arr[i]
    }
CGodo
fuente
No jsbench.github.io/#67b13d4e78cdd0d7a7346410d5becf12 muestra que el más rápido es "Bucle inverso, comparación implícita, código en línea" (105,221 ops / seg) mientras que "Bucle, valor en caché, código en línea" obtuvo solo 76,635 ops / seg (Chrome 38.0.2125.111 )
Viernes
@ Fr0sT Su punto de referencia es un escenario diferente, que atraviesa matrices del índice 1 a <= longitud. Por supuesto, esto va a conducir a resultados diferentes. Si intenta atravesar matrices de base cero con <longitud, lo que me parece el escenario habitual, descubrirá que los resultados se optimizan mejor con un bucle "for" normal (con una longitud en caché un poco más rápida).
CGodo
Kyopaxa cambió los puntos de referencia a (0 <= i <longitud), los resultados son los mismos. "Bucle inverso, comparación implícita, llamada a función" obtuvo 365 kops / seg, mientras que "Bucle, valor en caché, código en línea" obtuvo 350 kops / seg (FF 51)
Fr0sT
@ Fr0sT si cambia los bucles for en caché basados ​​en cero sin una comparación igual, como, por ejemplo for(let i=0, j=array.length; i < j; i++), los bucles for forward se aceleran considerablemente. En algunas pruebas que ejecuté ganó, en la mayoría estaba dentro del margen de error o el bucle inverso.
Isaac B
1
@IsaacB y todo, lo siento, no me di cuenta de que el banco es bastante incorrecto: todos los bucles directos iteran 1..length mientras que los bucles inversos iteran length..0 (el elemento arr [length] no es válido). Arregle las pruebas y ahora muestran los siguientes resultados: "Bucle, código en línea" 360,616 operaciones / seg. ± 0.27%, "Bucle, valor en caché, código en línea" 345.786 operaciones / seg. 2.18% (¡Sic!) "Bucle inverso, comparación implícita, código en línea "322,640 ops / sec ± 2.90% (!!!). Las pruebas fueron ejecutadas por FF51. Nuevo banco está aquí jsbench.github.io/#6bdfcd2692ba80c16a68c88554281570 . Parece que no tiene sentido uglificar los bucles.
Fr0sT
31

Si el orden no es importante, prefiero este estilo:

for(var i = array.length; i--; )

Almacena en caché la longitud y es mucho más corto para escribir. Pero iterará sobre la matriz en orden inverso.

Felix Kling
fuente
66
Lo acabas de matar.
Vignesh Raja
¿No necesitas i> = 0 ;?
MarwaAhmad
3
@MarwaAhmad: No. i--devuelve un número y una vez que el número es 0la condición es falseporque Boolean(0) === false.
Felix Kling
30

Es solo 2018, por lo que una actualización podría ser agradable ...

Y realmente tengo que estar en desacuerdo con la respuesta aceptada . Se difiere en diferentes navegadores. algunos lo hacen forEachmás rápido, algunos for-loop, y algunos while aquí es un punto de referencia en todos los métodos http://jsben.ch/mW36e

arr.forEach( a => {
  // ...
}

y dado que puede ver una gran cantidad de bucles for, for(a = 0; ... )entonces vale la pena mencionar que sin las variables 'var' se definirán globalmente y esto puede afectar drásticamente la velocidad, por lo que se ralentizará.

El dispositivo de Duff funciona más rápido en la ópera pero no en Firefox

var arr = arr = new Array(11111111).fill(255);
var benches =     
[ [ "empty", () => {
  for(var a = 0, l = arr.length; a < l; a++);
}]
, ["for-loop", () => {
  for(var a = 0, l = arr.length; a < l; ++a)
    var b = arr[a] + 1;
}]
, ["for-loop++", () => {
  for(var a = 0, l = arr.length; a < l; a++)
    var b = arr[a] + 1;
}]
, ["for-loop - arr.length", () => {
  for(var a = 0; a < arr.length; ++a )
    var b = arr[a] + 1;
}]
, ["reverse for-loop", () => {
  for(var a = arr.length - 1; a >= 0; --a )
    var b = arr[a] + 1;
}]
,["while-loop", () => {
  var a = 0, l = arr.length;
  while( a < l ) {
    var b = arr[a] + 1;
    ++a;
  }
}]
, ["reverse-do-while-loop", () => {
  var a = arr.length - 1; // CAREFUL
  do {
    var b = arr[a] + 1;
  } while(a--);   
}]
, ["forEach", () => {
  arr.forEach( a => {
    var b = a + 1;
  });
}]
, ["for const..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( const a in ar ) {
    var b = a + 1;
  }
}]
, ["for let..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( let a in ar ) {
    var b = a + 1;
  }
}]
, ["for var..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( var a in ar ) {
    var b = a + 1;
  }
}]
, ["Duff's device", () => {
  var len = arr.length;
  var i, n = len % 8 - 1;

  if (n > 0) {
    do {
      var b = arr[len-n] + 1;
    } while (--n); // n must be greater than 0 here
  }
  n = (len * 0.125) ^ 0;
  if (n > 0) { 
    do {
      i = --n <<3;
      var b = arr[i] + 1;
      var c = arr[i+1] + 1;
      var d = arr[i+2] + 1;
      var e = arr[i+3] + 1;
      var f = arr[i+4] + 1;
      var g = arr[i+5] + 1;
      var h = arr[i+6] + 1;
      var k = arr[i+7] + 1;
    }
    while (n); // n must be greater than 0 here also
  }
}]];
function bench(title, f) {
  var t0 = performance.now();
  var res = f();
  return performance.now() - t0; // console.log(`${title} took ${t1-t0} msec`);
}
var globalVarTime = bench( "for-loop without 'var'", () => {
  // Here if you forget to put 'var' so variables'll be global
  for(a = 0, l = arr.length; a < l; ++a)
     var b = arr[a] + 1;
});
var times = benches.map( function(a) {
                      arr = new Array(11111111).fill(255);
                      return [a[0], bench(...a)]
                     }).sort( (a,b) => a[1]-b[1] );
var max = times[times.length-1][1];
times = times.map( a => {a[2] = (a[1]/max)*100; return a; } );
var template = (title, time, n) =>
  `<div>` +
    `<span>${title} &nbsp;</span>` +
    `<span style="width:${3+n/2}%">&nbsp;${Number(time.toFixed(3))}msec</span>` +
  `</div>`;

var strRes = times.map( t => template(...t) ).join("\n") + 
            `<br><br>for-loop without 'var' ${globalVarTime} msec.`;
var $container = document.getElementById("container");
$container.innerHTML = strRes;
body { color:#fff; background:#333; font-family:helvetica; }
body > div > div {  clear:both   }
body > div > div > span {
  float:left;
  width:43%;
  margin:3px 0;
  text-align:right;
}
body > div > div > span:nth-child(2) {
  text-align:left;
  background:darkorange;
  animation:showup .37s .111s;
  -webkit-animation:showup .37s .111s;
}
@keyframes showup { from { width:0; } }
@-webkit-keyframes showup { from { width:0; } }
<div id="container"> </div>

nullqube
fuente
3
@Maykonn probablemente quisiste decir "y funciona en todas partes menos Opera Mini"
Dube
3
@Maykonn, que no aparece en la vista predeterminada porque el 0.18% de todos los usuarios tienen IE8 y no debe perder el tiempo tratando de soportarlo; en 2018 es un caballo muerto.
Dube
1
Definitivamente es cierto si considera a todos los usuarios de todo el mundo. Pero, desafortunadamente, en partes específicas del mundo, IE8 es relevante todavía.
Maykonn
1
Si puedo, no solo diferentes navegadores tendrán diferentes resultados con diferentes métodos, sino que los mismos navegadores tendrán diferentes resultados con diferentes entradas. Una gran matriz de solo números estará muy optimizada, mientras que una pequeña matriz mixta no.
Kaiido
1
@Tahlil Gracias.
nullqube
19

2014 Whileestá de vuelta

Solo piensa lógico.

Mira este

for( var index = 0 , length = array.length ; index < length ; index++ ) {

 //do stuff

}
  1. Necesita crear al menos 2 variables (índice, longitud)
  2. Necesita verificar si el índice es más pequeño que la longitud
  3. Necesidad de aumentar el índice
  4. el forbucle tiene 3 parámetros

Ahora dime por qué esto debería ser más rápido que:

var length = array.length;

while( --length ) { //or length--

 //do stuff

}
  1. Una variable
  2. Sin cheques
  3. el índice disminuye (las máquinas prefieren eso)
  4. while tiene solo un parámetro

Estaba totalmente confundido cuando Chrome 28 mostró que el ciclo for es más rápido que el tiempo. Esto debe haber ben algún tipo de

"Uh, todos están usando el ciclo for, centrémonos en eso cuando desarrollemos para Chrome"

Pero ahora, en 2014, el ciclo while está de vuelta en Chrome. es 2 veces más rápido, en otros navegadores / más antiguos siempre fue más rápido.

Últimamente hice algunas pruebas nuevas. Ahora, en el mundo real, esos códigos cortos no valen nada y jsperf no puede ejecutar correctamente el ciclo while, porque necesita recrear el array.length, lo que también lleva tiempo.

NO PUEDES obtener la velocidad real de un ciclo while en jsperf.

necesita crear su propia función personalizada y verificar eso con window.performance.now()

Y sí ... no hay forma de que el ciclo while sea simplemente más rápido.

El verdadero problema es en realidad el tiempo de manipulación / renderizado de dom / tiempo de dibujo o como quiera llamarlo.

Por ejemplo, tengo una escena de lienzo donde necesito calcular las coordenadas y las colisiones ... esto se hace entre 10-200 MicroSeconds (no milisegundos). En realidad, se necesitan varios milisegundos para procesar todo.

PERO

Hay otra forma súper eficiente usando el para loopen algunos casos ... por ejemplo para copiar / clonar una matriz

for(
 var i = array.length ;
 i > 0 ;
 arrayCopy[ --i ] = array[ i ] // doing stuff
);

Observe la configuración de los parámetros:

  1. Igual que en el ciclo while, estoy usando solo una variable
  2. Es necesario verificar si el índice es mayor que 0;
  3. Como puede ver, este enfoque es diferente de lo normal para el bucle que todos usan, ya que hago cosas dentro del tercer parámetro y también disminuyo directamente dentro de la matriz.

Dicho esto, esto confirma que máquinas como la ...

escribiendo que estaba pensando en hacerlo un poco más corto y eliminar algunas cosas inútiles y escribí este usando el mismo estilo:

for(
 var i = array.length ;
 i-- ;
 arrayCopy[ i ] = array[ i ] // doing stuff
);

Incluso si es más corto, parece que usar iuna vez más ralentiza todo. Es 1/5 más lento que el forbucle anterior y el anterior while.

Nota: el ;es muy importante después de la de looo sin{}

Incluso si solo te dijera que jsperf no es la mejor manera de probar scripts ... agregué estos 2 bucles aquí

http://jsperf.com/caching-array-length/40

Y aquí hay otra respuesta sobre el rendimiento en javascript

https://stackoverflow.com/a/21353032/2450730

Esta respuesta es para mostrar formas efectivas de escribir javascript. Entonces, si no puede leer eso, pregunte y recibirá una respuesta o leerá un libro sobre javascript http://www.ecma-international.org/ecma-262/5.1/

coco
fuente
Esta respuesta comienza de muy bien . Me di cuenta de que en los últimos años el forfue más rápido que el while, y una vez leí en crome-dev que fue exactamente por la razón que mencionas. Sería solo cuestión de tiempo antes de whilevolver a ponerse al día. ¡A partir de ese momento, la lógica en la primera parte de su respuesta se mantendrá (una vez más, sí)! Sin embargo, las implementaciones modernas ya no siguen rígidamente cada paso especificado por ecma (se optimizan). Como ahora su motor ya no es el cuello de botella más notable, ¡ahora se puede notar la falta de caché de la CPU en bucles inversos !
GitaarLAB
Explique, así que tal vez pueda corregir la respuesta o aprender algo nuevo. por cierto, la respuesta ahora tiene más de un año ... los navegadores pueden haber cambiado con el tiempo como siempre lo hacen ...
cocco
En mi opinión, mientras que (--length) es malo porque mientras técnicamente funciona porque 0 es falso, 0 y falso no son realmente lo mismo hablando semánticamente.
scott.korin
sí ... es una publicación anterior ahora ... pero sí, me encanta la simplicidad de mientras. Y seguro como lo mencionas en ambos casos necesitas saber qué escribir. Por otro lado, nunca tuve la necesidad de recorrer números negativos.
cocco
99
"las máquinas prefieren esto" suena como una oración de un anuncio de un detergente para la ropa
CocoaBean
11

http://jsperf.com/caching-array-length/60

La última revisión de la prueba, que preparé (reutilizando la anterior), muestra una cosa.

La longitud del almacenamiento en caché no es tan importante, pero no hace daño.

Cada primera ejecución de la prueba vinculada anteriormente (en la pestaña recién abierta) da los mejores resultados para los últimos 4 fragmentos (3º, 5º, 7º y 10º en gráficos) en Chrome, Opera y Firefox en mi Debian Squeeze de 64 bits ( mi hardware de escritorio ) Las ejecuciones posteriores dan resultados bastante diferentes.

Las conclusiones de rendimiento inteligente son simples:

  • Vaya con for loop (forward) y pruebe usando en !==lugar de <.
  • Si no tiene que reutilizar la matriz más tarde, entonces, mientras que el bucle en longitud disminuida y la shift()matriz de destrucción destructiva también es eficiente.

tl; dr

Hoy en día (2011.10) el siguiente patrón parece ser el más rápido.

for (var i = 0, len = arr.length; i !== len; i++) {
    ...
}

Tenga en cuenta que el almacenamiento en caché arr.lengthno es crucial aquí, por lo que puede probar i !== arr.lengthy el rendimiento no disminuirá, pero obtendrá un código más corto.


PD: Sé que en el fragmento con shift()su resultado podría usarse en lugar de acceder al elemento 0, pero de alguna manera pasé por alto eso después de reutilizar la revisión anterior (que tenía errores en los bucles while), y luego no quería perder los resultados ya obtenidos.

przemoc
fuente
¿Crear una variable dentro del ciclo como let current = arr [i] puede reducir un rendimiento (asignación de memoria grande)? ¿O sería mejor declarar actual antes del ciclo? ¿O usar arr [i] en todos los lugares dentro del bucle?
Makarov Sergey
8

¿"Mejor" como en puro rendimiento? o rendimiento Y legibilidad?

El "mejor" rendimiento puro es este, que utiliza un caché y el operador de prefijo ++ (mis datos: http://jsperf.com/caching-array-length/189 )

for (var i = 0, len = myArray.length; i < len; ++i) {
  // blah blah
}

Yo diría que el for-loop sin caché es el mejor equilibrio en tiempo de ejecución y tiempo de lectura del programador. Cada programador que comenzó con C / C ++ / Java no desperdiciará un ms teniendo que leer este.

for(var i=0; i < arr.length; i++){
  // blah blah
}
valbaca
fuente
2
+1 para legibilidad. No importa qué tan bien lense nombre, uno siempre tendría que hacer una doble toma en ese primer ciclo. La intención del segundo bucle es obvia.
Josh Johnson el
7

** almacena en caché la longitud de la matriz dentro del bucle, se eludirán algunos segundos de tiempo. Depende de los elementos de la matriz, si hay más elementos en la matriz, existe una gran diferencia con respecto a Ms de tiempo *

** **

sArr; //Array[158];

for(var i = 0 ; i <sArr.length ; i++) {
 callArray(sArr[i]); //function call
}

***end: 6.875ms***

** **

** **

sArr; //Array[158];
for(var i = 0,len = sArr.length ; i < len ; i++) {
  callArray(sArr[i]); //function call
}

***end: 1.354ms***

** **

Shushanth Pallegar
fuente
6

Esta parece ser la forma más rápida con diferencia ...

var el;
while (el = arr.shift()) {
  el *= 2;
}

Tenga en cuenta que esto consumirá la matriz, la comerá y no dejará nada ...

Sergio
fuente
2
arr.shift();en lugar de arr.pop() que se pueda evitar la matriz inversa.
Tintu C Raju
1
@Gargaroz si obtiene un JSON de un servicio web, por ejemplo, un servicio de chat o elementos en un catálogo de productos. Otra situación en la que solo necesita usar la matriz una vez puede ser, por ejemplo, un gráfico que obtiene muchas coordenadas en intervalos. Hay muchos ejemplos
Sergio
Genial, gracias por la explicación, muy amable de su parte; ¿Puedes señalarme en la dirección donde pueda encontrar más ejemplos para explotar este tipo de bucle?
Gargaroz
1
Actualmente en Chrome 53 y Firefox 48 es uno de los enfoques más lentos - verifique en perfjs.info/array-iteration
Pencroff
1
@Alireza está de acuerdo, tengo un comentario para eso en mi respuesta también.
Sergio
4

Es el año 2017 .

Hice algunas pruebas.

https://jsperf.com/fastest-way-to-iterate-through-an-array/

Parece que el while método es el más rápido en Chrome.

Parece que la disminución izquierda ( --i) es mucho más rápido que los otros ( ++i, i--,i++ ) en Firefox.

Este enfoque es el ayuno en promedio. Pero itera la matriz en orden inverso.

let i = array.length;
while (--i >= 0) {
    doSomething(array[i]);
}

Si el orden a futuro es importante, use este enfoque.

let ii = array.length;
let i = 0;
while (i < ii) {
    doSomething(array[i]);
    ++i;
}
SeregPie
fuente
3
Al usar la palabra clave let, en realidad está comparando el rendimiento de la creación del alcance en lugar del rendimiento del bucle. El uso let i = 0, ii = array.lengthen sus forbucles creará un nuevo alcance para esas variables dentro del forbloque. Sus whileejemplos no crean un nuevo alcance para las variables dentro del whilebloque y es por eso que son más rápidas. Si usa en varlugar de leten sus bucles for, verá que los bucles for siguen siendo tan rápidos como en 2017, pero más legibles.
CGodo
Aquí hay un jsperf de lo que estoy hablando: jsperf.com/javascript-loop-testing-let-vs-var
CGodo
Esto es solo un problema en Chrome. En otros navegadores vary lettienen el mismo rendimiento - stackoverflow.com/a/32345435/1785975
SeregPie
Interesante. De todos modos, no encuentro la declaración de " whileser más rápido en Chrome" precisa. Es solo si se usa letdebido a problemas de rendimiento de esa palabra clave en Chrome. Si usa varo con otros navegadores, fory whileson más o menos lo mismo, a veces fores aún más rápido dependiendo del punto de referencia, y es más compacto y legible en mi humilde opinión.
CGodo
2

Siempre escribo en el primer estilo.

Incluso si un compilador es lo suficientemente inteligente como para optimizarlo para matrices, ¿pero aún así es inteligente si estamos usando DOMNodeList aquí o algún objeto complicado con longitud calculada?

Sé cuál es la pregunta sobre las matrices, pero creo que es una buena práctica escribir todos sus bucles en un estilo.

Olegas
fuente
1
var arr = []; // The array
var i = 0;
while (i < arr.length) {
    // Do something with arr[i]
    i++;
}

i ++ es más rápido que ++ i, --i e i--

Además, puede guardar la última línea haciendo arr [i ++] la última vez que necesita acceder a i (pero esto puede ser difícil de depurar).

Puede probarlo aquí (con otras pruebas de bucle): http://jsperf.com/for-vs-whilepop/5

Forestrf
fuente
1
Actualmente en Chrome 53 es cierto, pero Firefox 48 tiene la misma velocidad - verifique perfjs.info/array-iteration
Pencroff
thunderguy.com/semicolon/2002/08/13/… dice que ++ies más rápido ...
IMTheNachoMan
1

A partir de septiembre de 2017, estas pruebas jsperf muestran que el siguiente patrón es el más eficaz en Chrome 60:

function foo(x) {
 x;
};
arr.forEach(foo);

¿Alguien puede reproducirse?

John Vandivier
fuente
Sí, parece ser más rápido. Sin embargo, intente ejecutar esto en IE11 y esas opciones son las más lentas. Y en Firefox 55.03, la 'vieja lente en caché reventada' está llegando a 12mil, un rendimiento asombroso en comparación con los 3.3k de cromo. Para ser consistente en el rendimiento en todos los navegadores, debe usar el ciclo promedio más rápido para cada navegador.
Plippie
0

He intentado otras formas de iterar una gran matriz y descubrí que reducir a la mitad la longitud de la matriz y luego iterar ambas mitades en un solo bucle es más rápido. Esta diferencia de rendimiento se puede ver al procesar grandes matrices .

var firstHalfLen =0;
var secondHalfLen = 0;
var count2=0;
var searchterm = "face";
var halfLen = arrayLength/2;
if(arrayLength%2==halfLen)
{
   firstHalfLen = Math.ceil(halfLen);
   secondHalfLen=Math.floor(halfLen);
}
else
{
   firstHalfLen=halfLen;
   secondHalfLen=halfLen;
}
for(var firstHalfCOunter=0,secondHalfCounter = arrayLength-secondHalfLen;
    firstHalfCOunter < firstHalfLen;
    firstHalfCOunter++)
{
  if(mainArray[firstHalfCOunter].search(new RegExp(searchterm, "i"))> -1)
  {
    count2+=1;
  }
  if(secondHalfCounter < arrayLength)
  {
    if(mainArray[secondHalfCounter].search(new RegExp(searchterm, "i"))> -1)
    {
        count2+=1;
    }
    secondHalfCounter++; 
  }
}

Alguna comparación de rendimiento (usando timer.js) entre la longitud en caché for-loop VS el método anterior.

http://jsfiddle.net/tejzpr/bbLgzxgo/

tejzpr
fuente
0

Otra prueba de jsperf.com: http://jsperf.com/while-reverse-vs-for-cached-length

El bucle while inverso parece ser el más rápido. El único problema es que mientras (--i) se detendrá en 0. ¿Cómo puedo acceder a la matriz [0] en mi bucle entonces?

Moritz Schmitz v. Hülst
fuente
2
Si lo hace, while (i--)entonces la veracidad de iserá probada antes de disminuir en lugar de disminuir y luego probar la veracidad.
Justin Fisher
0

Mientras que el bucle es un poco más rápido que para el bucle.

var len = arr.length;
while (len--) {
    // blah blah
}

Use el bucle while en su lugar

Azhar Zafar
fuente
-1

La solución más elegante que conozco es usar el mapa.

var arr = [1,2,3];
arr.map(function(input){console.log(input);});
Dan
fuente
46
La pregunta no es pedir la forma más lenta de iterar a través de un bucle
2013
-1

Prueba esto:

var myarray =[],
i = myarray.lenght;
while(i--){
// do somthing
}
li bing zhao
fuente
-1

La forma más rápida de recorrer una matriz es usando el filtro. El método filter () crea una nueva matriz con todos los elementos que pasan la prueba implementada por la función proporcionada.

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

const words = ['Floccinaucinihilipilification', 'limit', 'elite', 'Hippopotomonstrosesquipedaliophobia', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(new Date(), result);

Desde mi experiencia, siempre prefiero filtros, mapas, etc.

Rigin Oommen
fuente
La pregunta es sobre iterar sobre la matriz en el menor tiempo posible y no copiar la matriz en una nueva matriz.
Rahul Kadukar
-1

A partir de 2019, WebWorker ha sido más popular, para grandes conjuntos de datos, podemos usar WebWorker para procesar mucho más rápido mediante el uso completo de procesadores multi-core.

También tenemos Parallel.js que hacen que WebWorker sea mucho más fácil de usar para el procesamiento de datos.

Stackia
fuente