TypeScript, ciclo attraverso un dizionario


186

Nel mio codice, ho un paio di dizionari (come suggerito qui ) che è indicizzato String. Dato che questo è un po 'un tipo improvvisato, mi chiedevo se ci fossero suggerimenti su come sarei in grado di scorrere in sequenza ogni chiave (o valore, tutto ciò di cui ho bisogno le chiavi comunque). Qualsiasi aiuto apprezzato!

myDictionary: { [index: string]: any; } = {};

Hai provato for (var key in myDictionary) { }:? All'interno del ciclo, useresti keyper ottenere la chiave e myDictionary[key]per ottenere il valore
Ian

@Ian L'ho appena provato, non sembra funzionare. Nessun errore, ma all'interno dell'affermazione non scorre nulla
ben657,

1
@Ian Ah scusa, un po 'di codice altrove ci stava facendo casino. Funziona perfettamente! Vuoi renderlo una risposta in modo che io possa sceglierlo?
ben657,

Risposte:


296

Per scorrere sopra la chiave / i valori, utilizzare un for inciclo:

for (let key in myDictionary) {
    let value = myDictionary[key];
    // Use `key` and `value`
}

8
Questo non è sicuro in generale; ha bisogno del test hasOwnProperty (come nella risposta di Jamie Stark) o di qualcos'altro.
Don Hatch,

20
@DonHatch In realtà è molto sicuro in generale. Non è sicuro in casi molto specifici (come quando si includono librerie che modificano i prototipi in modo errato o se lo si modifica intenzionalmente in modo errato). Sta allo sviluppatore decidere se gonfiare il proprio codice con controlli molto probabilmente non necessari
Ian,

1
@Ian - Il mio pensiero è che non lo userei senza ulteriori garanzie poiché sembra un incidente in attesa di accadere, ad esempio se il codice trova la sua strada in una funzione di utilità, e quindi qualcuno passa quella funzione in un dizionario che non è semplicemente un Oggetto, ma piuttosto qualcosa con proprietà aggiuntive. Sì, come dici tu, spetta allo sviluppatore valutare la probabilità e la gravità di tale scenario. Per quanto mi riguarda, l'approccio meno gravoso dal punto di vista mentale è comportarsi come se in tutti i casi si realizzasse uno scenario del genere - meno a cui pensare.
Don Hatch,

5
@Ian Il problema è che ci sono troppe librerie che modificano i prototipi di oggetti. Sembra una cattiva idea sostenere questo tipo di modello quando esistono alternative semplici molto migliori, come ad esempio Object.keys(target).forEach(key => { let value = target(key); /* Use key, value here */ });. Se devi mostrare questo metodo, almeno menziona i rischi e le alternative migliori per coloro che non conoscono ancora meglio.
Yona Appletree,

8
Abbiamo già es6 e TypeScript. Perché il problema di scrivere hasOwnProperty per tutto il tempo rimane irrisolto? Anche nel 2017 e con tutta l'attenzione a JS. Sono così deluso.
Gherman,

170

<ES 2017 :

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

> = ES 2017 :

Object.entries(obj).forEach(
  ([key, value]) => console.log(key, value);
);

Questa è la soluzione che stavo cercando in quanto mi permetterà di ordinare le chiavi prima dell'iterazione
Andrew

Cordiali saluti, al momento non è supportato nel parco giochi TypeScript.
Seanny123,

1
Vedi qui come far Object.entriesfunzionare in TypeScript
Alex Klaus

Questo è perfetto
Piyush Choudhary il

67

Cosa ne pensi di questo?

for (let [key, value] of Object.entries(obj)) {
    ...
}

1
Richiede lib es2017 in tsconfig. Vedi stackoverflow.com/questions/45422573/…
Stéphane

Questo è ciò di cui avevo bisogno per superare l'errore Typescript su obj [key] "Nessuna firma indice ..." perché ho impostato esplicitamente il mio tipo obj su {[key: string]: string} e non volevo usare {[key: stringa]: qualsiasi}. Con questo posso solo accedere a "valore". Grazie
ggedde

E se si desidera ignorare keydel tutto, è sufficiente lasciare vuoto: [ , value]. (Grazie a questo commento del problema .)
Dominik,

51

C'è un avvertimento nel ciclo chiave / valore menzionato da Ian. Se è possibile che gli oggetti possano avere attributi associati al loro prototipo e quando si utilizza l' inoperatore, questi attributi verranno inclusi. Quindi vorrai assicurarti che la chiave sia un attributo della tua istanza e non del prototipo. IE precedenti sono noti per essere indexof(v)visualizzati come chiave.

for (const key in myDictionary) {
    if (myDictionary.hasOwnProperty(key)) {
        let value = myDictionary[key];
    }
}

3
Non cercare di dividere i capelli, ma poiché stiamo parlando di tipo script, non dovresti usare let key invece di var key? Bella risposta grazie.
Luke Dupin

3
In effetti, con la versione corrente di tipo script lo keye valuepuò essere const.
Patrick Desjardins,

È meglio non chiamare il hasOwnPropertysegno di spunta dall'oggetto di destinazione, ma piuttosto: ...if (Object.prototype.hasOwnProperty.call(myDictionary, key))...Altrimenti, se si utilizza eslint con la no-prototype-builtinsregola, verrà emesso un errore.
sceee

6

Il modo più breve per ottenere tutti i valori di dizionario / oggetto:

Object.keys(dict).map(k => dict[k]);

1

Per ottenere le chiavi:

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

1

Risposta Ians è buona, ma dovresti usare const invece di lasciare la chiave perché non viene mai aggiornata.

for (const key in myDictionary) {
    let value = myDictionary[key];
    // Use `key` and `value`
}
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.