TypeScript dla… z z indeksem / kluczem?

146

Jak opisano tutaj, TypeScript wprowadza pętlę foreach:

var someArray = [9, 2, 5];
for (var item of someArray) {
    console.log(item); // 9,2,5
}

Ale czy nie ma żadnego indeksu / klucza? Spodziewałbym się czegoś takiego:

for (var item, key of someArray) { ... }
Mick
źródło

Odpowiedzi:

274

.forEach ma już tę zdolność:

const someArray = [9, 2, 5];
someArray.forEach((value, index) => {
    console.log(index); // 0, 1, 2
    console.log(value); // 9, 2, 5
});

Ale jeśli chcesz możliwości for...of, możesz maptablicę do indeksu i wartości:

for (const { index, value } of someArray.map((value, index) => ({ index, value }))) {
    console.log(index); // 0, 1, 2
    console.log(value); // 9, 2, 5
}

To trochę za długie, więc może pomóc umieszczenie go w funkcji wielokrotnego użytku:

function toEntries<T>(a: T[]) {
    return a.map((value, index) => [index, value] as const);
}

for (const [index, value] of toEntries(someArray)) {
    // ..etc..
}

Wersja iterowalna

Będzie to działać w przypadku kierowania na ES3 lub ES5, jeśli kompilujesz z --downlevelIterationopcją kompilatora.

function* toEntries<T>(values: T[] | IterableIterator<T>) {
    let index = 0;
    for (const value of values) {
        yield [index, value] as const;
        index++;
    }
}

Array.prototype.entries () - ES6 +

Jeśli jesteś w stanie kierować reklamy na środowiska ES6 +, możesz użyć .entries()metody przedstawionej w odpowiedzi Arnavion .

David Sherret
źródło
Ale TypeScript kompiluje „for… of” do prostego „for”, które ma indeks var _i. Dlatego programiści TypeScript mogliby łatwo pozwolić nam użyć tego _i. Zobacz przykład placu zabaw: bit.ly/1R9SfBR
Mick
2
@Mick to zależy od celu. Podczas transpilacji do ES6 tego nie robi. Powodem tego dodatkowego kodu podczas transpilacji jest tylko sprawienie, aby kod ES6 działał w poprzednich wersjach.
David Sherret
3
Jak możesz zrobić sobie przerwę; w tym forEach?
João Silva
Również dobra odpowiedź stackoverflow.com/questions/34348937/ ...
Christopher Grigg
@ JoãoSilva możesz użyć Array.some()i zwrócić false w iteracji, którą chcesz zatrzymać. Nie jest tak wyraźny ani ładny jak a, breakale wystarczyłby do wykonania zadania. Osobiście mi się to nie podoba, prawdopodobnie przepisałbym iterację w inny sposób :) patrz stackoverflow.com/questions/2641347/ ...
Neek
35

„Old school javascript” na ratunek (dla tych, którzy nie znają / nie kochają programowania funkcjonalnego)

for (let i = 0; i < someArray.length ; i++) {
  let item = someArray[i];
}
Sylvain
źródło
2
Właściwie wolę tę odpowiedź najbardziej. Żadnych dodatkowych metod tylko do wygenerowania indeksu dla każdego elementu.
bluegrounds
Dziękuję ci, bardzoyyy muuuchh! Tego nie wiedzieliśmy :)
TSR
14

Aby uzyskać dostęp do indeksu podczas pracy z kolekcjami, można użyć operatora for..in TypeScript.

var test = [7,8,9];
for (var i in test) {
   console.log(i + ': ' + test[i]);
} 

Wynik:

 0: 7
 1: 8
 2: 9

Zobacz Demo

Karanvir Kang
źródło
Należy pamiętać, że „i” to łańcuch, a nie int z pętlą for..in. Wykonywanie operacji arytmetycznych z "i" spowoduje konkatenację łańcuchów. (i + 1) będzie równe „01”, na przykład gdy i = 0
Stéphane
for..inmoże również dać ci więcej, niż się spodziewałeś, ponieważ zawiera również wszystkie funkcje zadeklarowane w obiekcie. Na przykład:for (var prop in window.document) { console.log(prop); }
Ken Lyon
5

Lub inne oldschoolowe rozwiązanie:

var someArray = [9, 2, 5];
let i = 0;
for (var item of someArray) {
    console.log(item); // 9,2,5
    i++;
}
Galdor
źródło