Acceso al índice del elemento de matriz ES6 dentro del ciclo for-of

228

Podemos acceder a los elementos de la matriz utilizando un bucle for-of:

for (const j of [1, 2, 3, 4, 5]) {
  console.log(j);
}

¿Cómo puedo modificar este código para acceder también al índice actual? Quiero lograr esto usando la sintaxis for-of, ni forEach ni for-in.

Abdennour TOUMI
fuente

Respuestas:

351

Uso Array.prototype.keys:

for (const index of [1, 2, 3, 4, 5].keys()) {
  console.log(index);
}

Si desea acceder tanto a la clave como al valor, puede usarlo Array.prototype.entries()con la desestructuración :

for (const [index, value] of [1, 2, 3, 4, 5].entries()) {
  console.log(index, value);
}

Michał Perłakowski
fuente
64
En caso alguien se pregunta, he probado for-ofcon .entries()y es dos veces más lento en comparación con .forEach(). jsperf.com/for-of-vs-foreach-with-index
1
@ K48 es bueno saberlo, use "for-loop invertido" si desea tener el más rápido en es: incredible-web.com/blog/…
nimo23
3
Desafortunadamente, necesito ceder desde dentro de un bucle anidado. No se puede usar forEach, porque la función crea problemas de alcance para la yieldpalabra clave. Pero necesito acceso al índice para mi caso de uso, así que ... ;;supongo que es un bucle viejo y básico .
Kyle Baker,
2
@KyleBaker ¿Y qué tiene de malo un bucle for-of .entires()?
Michał Perłakowski
1
En lugar de bucle inverso, puede almacenar en caché la longitud jsperf.com/reverse-loop-vs-cache . Muy útil para el procesamiento iterable cuando puede procesar la transmisión sin crear grandes matrices en RAM. La velocidad de bucle no sería un cuello de botella, ya que en estos casos tendrá latencia de E / S.
x'ES
289

Array#entries devuelve el índice y el valor, si necesita ambos:

for (let [index, value] of array.entries()) {

}
Felix Kling
fuente
3
Con TypeScript: 'TS2495: Type IterableIterator no es un tipo de matriz o un tipo de cadena'. Parece que esto se resolverá: github.com/Microsoft/TypeScript/pull/12346
Johannes
2
También Internet Explorer no es compatible.
Sammi
1
No está bien. Lanza un error, por ejemplo, con document.styleSheets[0].cssRules.entries()o incluso document.styleSheets.entries()y probablemente muchas otras estructuras iterables DOM. Todavía tengo que usar _.forEach()delodash
Steven Pribilinskiy
2
@ Steven: Si no necesita el índice, simplemente puede hacerlo for (var value of document.styleSheets) {}. Si es necesario el índice se puede convertir el valor a un array primero a través de Array.from: for (let [index, value] of Array.from(document.styleSheets)) {}.
Felix Kling
1
¡Eso es bueno! Array.fromes FTW
Steven Pribilinskiy
28

En este mundo de nuevas y llamativas funciones nativas, a veces olvidamos lo básico.

for (let i = 0; i < arr.length; i++) {
    console.log('index:', i, 'element:', arr[i]);
}

Limpio, eficiente, y aún puedes seguir breakel ciclo. ¡Prima! ¡También puedes comenzar desde el final e ir hacia atrás con i--!

Nota adicional: si está utilizando mucho el valor dentro del ciclo, es posible que desee hacerlo const value = arr[i];en la parte superior del ciclo para obtener una referencia fácil y legible.

Chris
fuente
1
Sí. Buena, clara y simple. Ah, y así tienes una manera súper fácil de acceder a la clave / índice de la matriz.
Combinar
2
Por cierto, la condición debería verse así -> for (let i = 0; i <arr.length; i ++) sin el (-1) o no se repetirá en todos los elementos de la matriz.
Combinar
1
@Combine Buena captura! He actualizado mi respuesta para reflejar su nota.
Chris
44
Puede seguir breakuna for-ofy for (let [index, value] of array.entries())es mucho más fácil de leer. Retroceder es tan fácil como agregar .reverse().
Nigel B. Peck
3
Creo que esta es una respuesta perfectamente aceptable a esta pregunta. Nunca será la respuesta aceptada, pero ha ayudado a unas pocas docenas de personas o más que han buscado esta pregunta. Para eso es SO.
Danoram
3

en el contexto html / js, en los navegadores modernos, con otros objetos iterables que las matrices, también podríamos usar [Iterable] .entries ():

for(let [index, element] of document.querySelectorAll('div').entries()) {

    element.innerHTML = '#' + index

}
Joseph Merdrignac
fuente
Sí, esto funciona, mientras que otros mencionados anteriormente por @Steven Pribilinskiy otros métodos DOM devuelven objetos que no tienen un entriesmétodo para ellos.
Matanster
3

En un for..ofbucle podemos lograr esto a través de array.entries(). array.entriesdevuelve un nuevo objeto iterador de matriz. Un objeto iterador sabe cómo acceder a los elementos de uno iterable en ese momento, mientras realiza un seguimiento de su posición actual dentro de esa secuencia.

Cuando next()se llama al método en el iterador, se generan pares de valores clave. En estos pares de valores clave, el índice de matriz es la clave y el elemento de matriz es el valor.

let arr = ['a', 'b', 'c'];
let iterator = arr.entries();
console.log(iterator.next().value); // [0, 'a']
console.log(iterator.next().value); // [1, 'b']

UNA for..of bucle es básicamente una construcción que consume un iterable y recorre todos los elementos (usando un iterador debajo del capó). Podemos combinar esto array.entries()de la siguiente manera:

array = ['a', 'b', 'c'];

for (let indexValue of array.entries()) {
  console.log(indexValue);
}


// we can use array destructuring to conveniently
// store the index and value in variables
for (let [index, value] of array.entries()) {
   console.log(index, value);
}

Willem van der Veen
fuente
3

También puede manejar el índice usted mismo si necesita el índice , no funcionará si necesita la clave .

let i = 0;
for (const item of iterableItems) {
  // do something with index
  console.log(i);

  i++;
}
TintinSansYeux
fuente
0

Para aquellos que usan objetos que no son como una Arraymatriz, incluso pueden crear su propio iterable fácilmente para que aún puedan usarlo for ofpara cosas como las localStorageque realmente solo tienen un length:

function indexerator(length) {
    var output = new Object();
    var index = 0;
    output[Symbol.iterator] = function() {
        return {next:function() {
            return (index < length) ? {value:index++} : {done:true};
        }};
    };
    return output;
}

Luego solo dale un número:

for (let index of indexerator(localStorage.length))
    console.log(localStorage.key(index))
Hashbrown
fuente
0

es6 for...in

for(const index in [15, 64, 78]) {                        
    console.log(index);
}
solanki ...
fuente
55
La pregunta es acerca de un for...ofbucle, no unfor...in
Abraham Hernandez
3
for...ines parte de la especificación ECMAScript original (es decir, "es1"). Además, tenga en cuenta que for...inestá destinado a iterar sobre las propiedades del objeto. Si bien puede iterar sobre matrices, puede que no lo haga en el orden esperado. Ver más en la documentación de MDN
Boaz
0

Otro enfoque podría estar usando Array.prototype.forEach()como

Array.from({
  length: 5
}, () => Math.floor(Math.random() * 5)).forEach((val, index) => {
  console.log(val, index)
})

Saksham
fuente
-6
var fruits = ["apple","pear","peach"];
for (fruit of fruits) {
    console.log(fruits.indexOf(fruit));
    //it shows the index of every fruit from fruits
}

el bucle for atraviesa la matriz, mientras que la propiedad indexof toma el valor del índice que coincide con la matriz. PD: este método tiene algunos defectos con los números, así que usa frutas

Edwin Felipe
fuente
2
Esto lleva O (n ^ 2) tiempo.
Harry
3
En los casos en que el rendimiento no es importante, esto todavía no proporciona todos los índices correctos cuando hay fruta duplicada. Por ejemplo, para ["apple", "apple", "pear"]los índices dados son en 0, 0, 2lugar de 0, 1, 2.
trichoplax