Acesso ao índice de elemento de matriz ES6 dentro do loop for-of


227

Podemos acessar elementos do array usando um loop for-of:

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

Como posso modificar esse código para acessar também o índice atual? Quero conseguir isso usando a sintaxe for-of, nem forEach nem for-in.

Respostas:


348

Use Array.prototype.keys:

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

Se você deseja acessar a chave e o valor, pode usar Array.prototype.entries()com a desestruturação :

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


64
Caso alguém se pergunte, eu testei for-ofcom .entries()e é duas vezes mais lento em comparação com .forEach(). jsperf.com/for-of-vs-foreach-with-index

1
@ K48 bom saber, use "revertida para loop" se você quer ter o mais rápido em es: incredible-web.com/blog/...
nimo23

3
Infelizmente, preciso render de dentro de um loop aninhado. Não é possível usar o forEach, porque a função cria problemas de escopo para a yieldpalavra - chave. Mas preciso acessar o índice para o meu caso de uso, então ... ;;acho que é um loop antigo básico .
Kyle Baker

2
@KyleBaker E o que há de errado com um loop for-of .entires()?
Michał Perłakowski

1
Em vez disso, loop reverso, você pode armazenar em cache o comprimento jsperf.com/reverse-loop-vs-cache . Útil para processamento iterável quando você pode processar o fluxo sem criar grandes matrizes na RAM. A velocidade do loop não seria um gargalo, pois você terá latência de E / S nesses casos.
x'ES 19/02/19

289

Array#entries retorna o índice e o valor, se você precisar de ambos:

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

}

3
Com o TypeScript: 'TS2495: Type IterableIterator não é um tipo de matriz ou de seqüência de caracteres'. Parece que isso será resolvido: github.com/Microsoft/TypeScript/pull/12346
Johannes

2
Também não há suporte para o Internet Explorer.
Sammi 24/03

1
Não é legal. Lança um erro, por exemplo, com document.styleSheets[0].cssRules.entries()ou mesmo document.styleSheets.entries()e provavelmente muitas outras estruturas iteráveis ​​do DOM. Ainda tem que usar _.forEach()fromlodash
Steven Pribilinskiy 7/17

2
@ Steven: Se você não precisa do índice, pode fazer for (var value of document.styleSheets) {}. Se você precisa fazer o índice pode converter o valor para uma matriz primeira via Array.from: for (let [index, value] of Array.from(document.styleSheets)) {}.
Felix Kling

1
Isso é bom! Array.fromé FTW
Steven Pribilinskiy

28

Nesse mundo de novas funções nativas chamativas, às vezes esquecemos o básico.

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

Limpo, eficiente e você ainda pode fazer breako loop. Bônus! Você também pode começar do final e retroceder i--!

Nota adicional: se você estiver usando muito o valor dentro do loop, convém fazer isso const value = arr[i];na parte superior do loop para obter uma referência fácil e legível.


1
Sim. Bom, claro e simples. Ah, e assim você tem uma maneira super fácil de acessar a chave / índice da matriz.
Combine

2
A propósito, a condição deve se parecer com isso -> for (deixe i = 0; i <comprimento da arroba; i ++) sem o (-1) ou não ocorrerá um loop em todos os elementos da matriz.
Combine

1
@ Bom Combinar captura! Atualizei minha resposta para refletir sua nota.
chris

4
Você pode ainda breakuma for-ofe for (let [index, value] of array.entries())é muito mais fácil de ler. Retroceder é tão fácil quanto adicionar .reverse().
Nigel B. Peck

2
Eu acho que essa é uma resposta perfeitamente aceitável para essa pergunta. Essa nunca será a resposta aceita, mas ajudou algumas dezenas de pessoas ou mais que procuraram por essa pergunta. É para isso que serve.
Danoram 11/10/19

3

no contexto html / js, em navegadores modernos, com outros objetos iteráveis ​​que Arrays, também poderíamos usar [Iterable] .entries ():

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

    element.innerHTML = '#' + index

}

Sim, isso funciona, enquanto outros mencionados acima por @Steven Pribilinskiy outros métodos DOM retornam objetos que não possuem um entriesmétodo para eles.
matanster

3

Em um for..ofloop, podemos conseguir isso via array.entries(). array.entriesretorna um novo objeto iterador de matriz. Um objeto iterador sabe como acessar itens de um iterável por vez, mantendo o controle de sua posição atual nessa sequência.

Quando o next()método é chamado no iterador, os pares de valores de chave são gerados. Nesses pares de valores-chave, o índice da matriz é a chave e o item da matriz é o valor.

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

Um for..ofloop é basicamente uma construção que consome um iterável e percorre todos os elementos (usando um iterador sob o capô). Podemos combinar isso array.entries()da seguinte maneira:

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


3

Você também pode lidar com o índice se precisar do índice ; ele não funcionará se você precisar da chave .

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

  i++;
}

0

Para aqueles que usam objetos que não são Arrayparecidos com um array ou mesmo com array, você pode criar seu próprio iterável facilmente para continuar usando for ofcoisas como as localStorageque realmente têm apenas 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;
}

Em seguida, basta alimentar um número:

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

0

es6 for...in

for(const index in [15, 64, 78]) {                        
    console.log(index);
}

5
A pergunta é sobre um for...ofloop, não umfor...in
Abraham Hernandez

3
for...infaz parte da especificação original do ECMAScript (ou seja, "es1"). Além disso, observe que for...inse destina à iteração sobre as propriedades do objeto. Embora possa iterar sobre matrizes, pode não fazê-lo na ordem esperada. Veja mais na documentação
Boaz

0

Outra abordagem poderia estar usando Array.prototype.forEach()como

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


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

o loop for percorre a matriz, enquanto a propriedade indexof obtém o valor do índice que corresponde à matriz. PD este método tem algumas falhas com números, então use frutas


2
Isso leva tempo O (n ^ 2).
Harry

3
Nos casos em que o desempenho não é importante, isso ainda não fornece todos os índices corretos quando há frutos duplicados. Por exemplo, para ["apple", "apple", "pear"]os índices fornecidos são em 0, 0, 2vez de 0, 1, 2.
Trichoplax
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.