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; } = {};

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`
}

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

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)) {
    ...
}

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

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

0

Aby zdobyć klucze:

function GetDictionaryKeysAsArray(dict: {[key: string]: string;}): string[] {
  let result: string[] = [];
  Object.keys(dict).map((key) =>
    result.push(key),
  );
  return result;
}

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`
}
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.