Dostęp do indeksu elementów tablicy ES6 wewnątrz pętli for-of


226

Możemy uzyskać dostęp do elementów tablicy za pomocą pętli for-of:

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

Jak mogę zmodyfikować ten kod, aby uzyskać dostęp do bieżącego indeksu? Chcę to osiągnąć przy użyciu składni for-of, ani forEach, ani for-in.

Odpowiedzi:


347

Użyj Array.prototype.keys:

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

Jeśli chcesz uzyskać dostęp zarówno do klucza, jak i do wartości, możesz użyć Array.prototype.entries()z destrukcją :

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


64
W przypadku gdy ktoś zastanawia się, testowałem for-ofze .entries()i to dwukrotnie w porównaniu do powolny .forEach(). jsperf.com/for-of-vs-foreach-with-index

1
@ K48 miło wiedzieć, użyj „odwróconej pętli for”, jeśli chcesz mieć najszybszy w es: incredible-web.com/blog/…
nimo23 15.01.2018

3
Niestety muszę ustąpić z wnętrza zagnieżdżonej pętli. Nie można użyć forEach, ponieważ funkcja powoduje problemy z zakresem dla yieldsłowa kluczowego. Ale potrzebuję dostępu do indeksu dla mojego przypadku użycia, więc ... ;;to chyba podstawowa stara pętla.
Kyle Baker

2
@KyleBaker A co jest nie tak z pętlą for-of .entires()?
Michał Perłakowski

1
Zamiast odwróconej pętli możesz buforować długość jsperf.com/reverse-loop-vs-cache . Przydatne do iterowalnego przetwarzania, gdy można przetwarzać strumień bez tworzenia dużych tablic w pamięci RAM. Szybkość pętli nie byłaby wąskim gardłem, ponieważ w takich przypadkach będziesz mieć opóźnienie we / wy.
x'ES

289

Array#entries zwraca indeks i wartość, jeśli potrzebujesz obu:

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

}

3
W przypadku TypeScript: „TS2495: Type IterableIterator nie jest typem tablicowym ani ciągiem znaków”. Wygląda na to, że to zostanie rozwiązane: github.com/Microsoft/TypeScript/pull/12346
Johannes

2
Również Internet Explorer nie jest obsługiwany.
Sammi

1
Niemiły. Zgłasza błąd, np. Z document.styleSheets[0].cssRules.entries()lub nawet document.styleSheets.entries()i prawdopodobnie wiele innych struktur iterowalnych DOM. Nadal muszę korzystać _.forEach()zlodash
Steven Pribilinskiy

2
@Steven: Jeśli nie potrzebujesz indeksu, możesz to zrobić for (var value of document.styleSheets) {}. Jeśli musisz indeksu można przekonwertować wartości do tablicy najpierw poprzez Array.from: for (let [index, value] of Array.from(document.styleSheets)) {}.
Felix Kling

1
To miłe! Array.fromjest FTW
Steven Pribilinskiy

28

W tym świecie efektownych nowych natywnych funkcji czasami zapominamy o podstawach.

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

Czysty, wydajny i nadal możesz breakzapętlić. Premia! Możesz także zacząć od końca i cofnąć się oi-- !

Uwaga dodatkowa: jeśli często używasz wartości w pętli, możesz chcieć zrobić const value = arr[i];na górze pętli, aby uzyskać łatwe i czytelne odniesienie.


1
Tak. Dobry, jasny i prosty. Och, i w ten sposób masz bardzo łatwy sposób na uzyskanie dostępu do klucza / indeksu tablicy.
Połącz

2
Nawiasem mówiąc, warunek powinien wyglądać następująco -> for (niech i = 0; i <arr.length; i ++) bez (-1), inaczej nie będzie on zapętlał wszystkich elementów tablicy.
Połącz

1
@Combine Good catch! Zaktualizowałem moją odpowiedź, aby odzwierciedlić Twoją notatkę.
Chris

4
Można nadal i jest o wiele łatwiejsze do odczytania. Cofanie się jest tak proste, jak dodawanie . breakfor-offor (let [index, value] of array.entries()).reverse()
Nigel B. Peck

2
Myślę, że jest to całkowicie akceptowalna odpowiedź na to pytanie. To nigdy nie będzie akceptowana odpowiedź, ale pomogła kilkudziesięciu osobom lub więcej, które szukały tego pytania. Po to jest SO.
Danoram

3

w kontekście html / js, w nowoczesnych przeglądarkach, z innymi obiektami iterowalnymi niż tablice moglibyśmy również użyć [Iterable] .entries ():

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

    element.innerHTML = '#' + index

}

Tak, to działa, podczas gdy inne wymienione powyżej przez @Steven Pribilinskiy inne metody DOM zwracają obiekty, które nie mają entriesdla nich żadnej metody.
matanster

3

W for..ofpętli możemy to osiągnąć poprzez array.entries(). array.entrieszwraca nowy obiekt iteratora Array. Obiekt iteratora wie, jak uzyskać dostęp do elementów z iterowalnego w tym samym czasie, jednocześnie śledząc jego bieżącą pozycję w tej sekwencji.

Po next()wywołaniu metody generowane są pary wartości iteratora. W tych parach wartości klucza indeks tablicy jest kluczem, a element tablicy jest wartością.

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

for..ofPętli jest zasadniczo konstruktem, który zużywa iterowalny i pętle przez wszystkie elementy (z zastosowaniem iteracyjnej pod wyciągiem). Możemy to połączyć array.entries()w następujący sposób:

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

Możesz także samodzielnie obsługiwać indeks, jeśli potrzebujesz indeksu , nie będzie działać, jeśli potrzebujesz klucza .

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

  i++;
}

0

Dla tych, którzy używają obiektów, które nie są Arrayani nawet podobne do tablicy, możesz łatwo zbudować własną iterowalność, dzięki czemu nadal możesz używać for ofdo rzeczy takich, localStoragektóre naprawdę mają tylko 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;
}

Następnie podaj numer:

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
Pytanie dotyczy for...ofpętli, a niefor...in
Abraham Hernandez

3
for...injest częścią oryginalnej specyfikacji ECMAScript (tj. „es1”). Zauważ też, że for...insłuży to do iteracji właściwości obiektu. Chociaż może iterować po tablicach, może nie robić tego w oczekiwanej kolejności. Zobacz więcej w dokumentacji MDN
Boaz

0

Innym podejściem może być użycie Array.prototype.forEach()jako

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
}

pętla for przechodzi przez tablicę, a właściwość indexof przyjmuje wartość indeksu pasującego do tablicy. PD ta metoda ma pewne wady z liczbami, więc używaj owoców


2
Zajmuje to czas O (n ^ 2).
Harry,

3
W przypadkach, w których wydajność nie jest ważna, nadal nie daje wszystkich poprawnych indeksów, gdy występują duplikaty owoców. Na przykład dla ["apple", "apple", "pear"]podanych indeksów 0, 0, 2zamiast 0, 1, 2.
trichoplax
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.