Accesso all'indice dell'elemento dell'array ES6 all'interno del ciclo for-of


227

Possiamo accedere agli elementi dell'array usando un ciclo for-of:

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

Come posso modificare questo codice per accedere anche all'indice corrente? Voglio ottenere questo usando la sintassi for-of, né forEach né for-in.

Risposte:


349

Utilizzare Array.prototype.keys:

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

Se si desidera accedere sia alla chiave che al valore, è possibile utilizzare Array.prototype.entries()con destrutturazione :

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


64
Nel caso qualcuno si chieda, ho provato for-ofcon .entries()ed è due volte più lento rispetto a .forEach(). jsperf.com/for-of-vs-foreach-with-index

1
@ K48 bello da sapere, usa "reverse-for-loop" se vuoi avere il più veloce in es: incredible-web.com/blog/…
nimo23

3
Sfortunatamente, devo cedere dall'interno di un ciclo nidificato. Non è possibile utilizzare forEach, poiché la funzione crea problemi di ambito per la yieldparola chiave. Ma ho bisogno di accedere all'indice per il mio caso d'uso, quindi ... ;;credo che il vecchio ciclo di base lo sia.
Kyle Baker,

2
@KyleBaker E cosa c'è che non va in un ciclo for-of .entires()?
Michał Perłakowski,

1
Al contrario, è possibile eseguire il reverse loop della lunghezza della cache jsperf.com/reverse-loop-vs-cache . Utile per l'elaborazione iterabile quando si è in grado di elaborare lo streaming senza creare grandi array nella RAM. La velocità del loop non sarebbe un collo di bottiglia in quanto in questi casi avrai latenza I / O.
xES

289

Array#entries restituisce l'indice e il valore, se sono necessari entrambi:

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

}

3
Con TypeScript: "TS2495: Type IterableIterator non è un tipo di array o un tipo di stringa". Sembra che questo sarà risolto: github.com/Microsoft/TypeScript/pull/12346
Johannes

2
Anche Internet Explorer non è supportato.
Sammi,

1
Non bello. Genera un errore, ad esempio con document.styleSheets[0].cssRules.entries()o anche document.styleSheets.entries()e probabilmente molte altre strutture iterabili DOM. Devo ancora usare _.forEach()dalodash
Steven Pribilinskiy il

2
@Steven: se non hai bisogno dell'indice, puoi semplicemente farlo for (var value of document.styleSheets) {}. Se è necessario l'indice è possibile convertire il valore in un array prima via Array.from: for (let [index, value] of Array.from(document.styleSheets)) {}.
Felix Kling,

1
Bello! Array.fromè FTW
Steven Pribilinskiy il

28

In questo mondo di appariscenti nuove funzioni native, a volte dimentichiamo le basi.

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

Pulito, efficiente e puoi ancora fare breakil giro. Bonus! Puoi anche iniziare dalla fine e tornare indietro con i--!

Nota aggiuntiva: se si utilizza molto il valore all'interno del ciclo, si consiglia di farlo const value = arr[i];nella parte superiore del ciclo per un riferimento facile e leggibile.


1
Sì. Buono, chiaro e semplice. Oh, e così hai un modo semplicissimo per accedere alla chiave / indice dell'array.
Combina il

2
A proposito, la condizione dovrebbe assomigliare a questa -> for (let i = 0; i <arr.length; i ++) senza il segno (-1) o non eseguirà il ciclo in tutti gli elementi dell'array.
Combina il

1
@Combine Buona cattura! Ho aggiornato la mia risposta per riflettere la tua nota.
chris,

4
È ancora possibile breakun for-ofe for (let [index, value] of array.entries())è molto più facile da leggere. Andare indietro è facile come aggiungere .reverse().
Nigel B. Peck,

2
Penso che questa sia una risposta perfettamente accettabile a questa domanda. Non sarà mai la risposta accettata, ma ha aiutato qualche decina di persone o più che hanno cercato questa domanda. Questo è lo scopo di SO.
Danoram,

3

nel contesto html / js, sui browser moderni, con altri oggetti iterabili oltre agli array potremmo anche usare [Iterable] .entries ():

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

    element.innerHTML = '#' + index

}

Sì, questo funziona, mentre altri sopra menzionati da @Steven Pribilinskiy altri metodi DOM restituiscono oggetti che non hanno un entriesmetodo per loro.
matanster

3

In un for..ofciclo possiamo raggiungere questo tramite array.entries(). array.entriesrestituisce un nuovo oggetto iteratore di array. Un oggetto iteratore sa come accedere agli oggetti da uno iterabile alla volta, tenendo traccia della sua posizione corrente all'interno di quella sequenza.

Quando il next()metodo viene chiamato, vengono generate le coppie di valori chiave dell'iteratore. In queste coppie di valori chiave l' indice dell'array è la chiave e l'elemento dell'array è il valore.

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

Un for..ofloop è fondamentalmente un costrutto che consuma un iterabile e scorre attraverso tutti gli elementi (usando un iteratore sotto il cofano). Possiamo combinarlo con array.entries()nel modo seguente:

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

Puoi anche gestire tu stesso l'indice se hai bisogno dell'indice , non funzionerà se ti serve la chiave .

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

  i++;
}

0

Per coloro che usano oggetti che non sono Arrayo addirittura simili a array, puoi creare facilmente il tuo iterabile in modo da poterlo ancora usare for ofper cose come quelle localStorageche hanno solo 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;
}

Quindi basta dargli un numero:

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
La domanda è su un for...ofciclo non unfor...in
Abraham Hernandez,

3
for...infa parte della specifica ECMAScript originale (es. "es1"). Inoltre, si noti che for...inè pensato per iterare sulle proprietà degli oggetti. Mentre può scorrere su array, potrebbe non farlo nell'ordine previsto. Vedi di più nella documentazione MDN
Boaz

0

Un altro approccio potrebbe essere usare Array.prototype.forEach()come

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
}

il ciclo for attraversa l'array, mentre la proprietà indexof assume il valore dell'indice che corrisponde all'array. PD questo metodo ha alcuni difetti con i numeri, quindi usa la frutta


2
Questo richiede tempo O (n ^ 2).
Harry,

3
Nei casi in cui le prestazioni non sono importanti, ciò non fornisce ancora tutti gli indici corretti in presenza di frutti duplicati. Ad esempio, per ["apple", "apple", "pear"]gli indici forniti sono 0, 0, 2invece di 0, 1, 2.
trichoplax,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.