TypeScript, zapętlanie słownika

184

W moim kodzie mam kilka słowników (jak sugerowano tutaj ), które są indeksowane przez String. Z uwagi na to, że jest to trochę improwizowany typ, zastanawiałem się, czy są jakieś sugestie dotyczące tego, w jaki sposób mógłbym zapętlać każdy klucz (lub wartość, i tak potrzebuję kluczy). Każda pomoc doceniona!

myDictionary: { [index: string]: any; } = {};
ben657
źródło
Próbowałeś for (var key in myDictionary) { }:? Wewnątrz pętli użyłbyś keyklucza, myDictionary[key]aby uzyskać wartość
Ian
@ Ian Właśnie tego spróbowałem, nie działa. Brak błędów, ale nic nie działa w instrukcji
ben657
1
@Ian Ah przepraszam, jakiś kod gdzie indziej zadzierał z tym. To działa idealnie! Czy chcesz, aby była to odpowiedź, abym mógł ją wybrać?
ben657

Odpowiedzi:

294

Aby zapętlić klucz / wartości, użyj for inpętli:

for (let key in myDictionary) {
    let value = myDictionary[key];
    // Use `key` and `value`
}
Ian
źródło
8
Zasadniczo nie jest to bezpieczne; potrzebuje testu hasOwnProperty (jak w odpowiedzi Jamiego Starka) lub czegoś innego.
Don Hatch,
20
@DonHatch Ogólnie jest to bardzo bezpieczne. Nie jest to bezpieczne w bardzo szczególnych przypadkach (np. Gdy dołączasz biblioteki, które nieprawidłowo modyfikują prototypy lub celowo modyfikują prototypy niepoprawnie). Deweloper decyduje, czy nadepnąć na swój kod za pomocą najbardziej prawdopodobnych, niepotrzebnych kontroli
Ian
1
@Ian - Myślę, że nie użyłbym go bez dodatkowych zabezpieczeń, ponieważ wydaje się, że czeka go wypadek, np. Jeśli kod znajdzie się w funkcji narzędziowej, a następnie ktoś przekaże tej funkcji słownik, który nie jest po prostu Obiekt, ale raczej coś o dodatkowych właściwościach. Tak, jak mówisz, do programisty należy ocena prawdopodobieństwa i powagi takiego scenariusza. Dla mnie najmniej uciążliwym psychicznie podejściem jest zachowywać się tak, jakby taki scenariusz miał miejsce we wszystkich przypadkach - mniej o tym myśleć.
Don Hatch
5
@Ian Problem polega na tym, że istnieje zbyt wiele bibliotek, które modyfikują prototypy obiektów. Wydaje się złym pomysłem promowanie tego rodzaju wzorca, gdy istnieją znacznie lepsze proste alternatywy, takie jak Object.keys(target).forEach(key => { let value = target(key); /* Use key, value here */ });. Jeśli musisz pokazać tę metodę, przynajmniej wspomnij o ryzyku i lepszych alternatywach dla tych, którzy jeszcze nie wiedzą lepiej.
Yona Appletree
8
Mamy już es6 i TypeScript. Dlaczego problem pisania hasOwnProperty cały czas pozostaje nierozwiązany? Nawet w 2017 roku i z całą uwagą na JS. Jestem bardzo rozczarowany.
Gherman
169

<ES 2017 :

Object.keys(obj).forEach(key => {
  let value = obj[key];
});

> = ES 2017 :

Object.entries(obj).forEach(
  ([key, value]) => console.log(key, value);
);
Stephen Paul
źródło
Jest to rozwiązanie, którego szukałem, ponieważ pozwoli mi posortować klucze przed iteracją
Andrew
Do Twojej wiadomości, obecnie nie jest to obsługiwane na placu zabaw TypeScript.
Seanny123
1
Zobacz tutaj, jak Object.entriespracować w TypeScript
Alex Klaus
To jest idealne
Piyush Choudhary
67

Co powiesz na to?

for (let [key, value] of Object.entries(obj)) {
    ...
}
Radon Rosborough
źródło
1
Wymaga lib es2017 w tsconfig. Zobacz stackoverflow.com/questions/45422573/…
Stéphane
Właśnie tego potrzebowałem, aby ominąć błąd maszynopisu na obj [klucz] „Brak podpisu indeksu ...”, ponieważ jawnie ustawiłem mój typ obj jako {[klucz: ciąg]: ciąg} i nie chciałem używać {[klucz: string]: any}. Dzięki temu mogę po prostu uzyskać dostęp do „wartości”. Dzięki
ggedde
A jeśli chcesz ignorować keyw ogóle, po prostu zostawić puste: [ , value]. (Dzięki komentarzowi do tego wydania .)
Dominik
50

Ian wspomniał o jednym zastrzeżeniu dla pętli klucz / wartość. Jeśli możliwe jest, że Obiekty mogą mieć atrybuty dołączone do ich Prototypu, a gdy użyjesz inoperatora, atrybuty te zostaną uwzględnione. Dlatego upewnij się, że klucz jest atrybutem Twojego wystąpienia, a nie prototypu. Starsze IE są znane z tego, że indexof(v)pojawiają się jako klucz.

for (const key in myDictionary) {
    if (myDictionary.hasOwnProperty(key)) {
        let value = myDictionary[key];
    }
}
Jamie Starke
źródło
2
Nie próbujemy dzielić włosów, ale skoro mówimy o typie pisma, nie powinieneś używać klawisza let zamiast var key? Dobra odpowiedź, dziękuję.
Luke Dupin,
3
W rzeczywistości przy obecnej wersji skryptu typu keyi valuemoże być const.
Patrick Desjardins
Lepiej nie wywoływać hasOwnPropertyczeku z obiektu docelowego, zamiast tego wykonaj następujące czynności: W przeciwnym ...if (Object.prototype.hasOwnProperty.call(myDictionary, key))...razie, jeśli używasz eslinta z no-prototype-builtinsregułą, wyświetli błąd.
sceee
5

Najkrótszy sposób na uzyskanie wszystkich wartości słownika / obiektu:

Object.keys(dict).map(k => dict[k]);
k06a
źródło
0

Aby zdobyć klucze:

function GetDictionaryKeysAsArray(dict: {[key: string]: string;}): string[] {
  let result: string[] = [];
  Object.keys(dict).map((key) =>
    result.push(key),
  );
  return result;
}
Ribeiro
źródło
0

Ians Answer jest dobry, ale powinieneś użyć const zamiast let dla klucza, ponieważ nigdy nie jest aktualizowany.

for (const key in myDictionary) {
    let value = myDictionary[key];
    // Use `key` and `value`
}
finnk
źródło