TypeScript, boucle dans un dictionnaire

186

Dans mon code, j'ai quelques dictionnaires (comme suggéré ici ) qui sont indexés par String. Étant donné que cela était un peu improvisé, je me demandais s'il y avait des suggestions sur la façon dont je pourrais boucler chaque clé (ou valeur, tout ce dont j'ai besoin de toute façon). Toute aide appréciée!

myDictionary: { [index: string]: any; } = {};
ben657
la source
Avez-vous essayé for (var key in myDictionary) { }:? À l'intérieur de la boucle, vous utiliseriez keypour obtenir la clé et myDictionary[key]pour obtenir la valeur
Ian
@Ian J'ai juste essayé ça, ça ne marche pas. Aucune erreur, mais rien ne s'exécute dans la déclaration
ben657
1
@Ian Ah désolé, du code ailleurs le dérangeait. Cela fonctionne parfaitement! Voulez-vous en faire une réponse pour que je puisse la choisir?
ben657

Réponses:

296

Pour boucler sur la clé / les valeurs, utilisez une for inboucle:

for (let key in myDictionary) {
    let value = myDictionary[key];
    // Use `key` and `value`
}
Ian
la source
8
Ce n'est pas sûr en général; il a besoin du test hasOwnProperty (comme dans la réponse de Jamie Stark) ou autre chose.
Don Hatch
20
@DonHatch C'est en fait très sûr en général. Ce n'est pas sûr dans des cas très spécifiques (comme lorsque vous incluez des bibliothèques qui modifient des prototypes de manière incorrecte ou qui modifient délibérément des prototypes de manière incorrecte). Il appartient au développeur de gonfler son code avec des vérifications très probablement inutiles
Ian
1
@Ian - Je pense que je ne l'utiliserais pas sans garanties supplémentaires car cela semble être un accident en attente de se produire, par exemple si le code trouve son chemin dans une fonction utilitaire, puis que quelqu'un passe à cette fonction un dictionnaire qui n'est pas simplement un Objet, mais plutôt quelque chose avec des propriétés supplémentaires. Oui, comme vous le dites, c'est au développeur de peser la probabilité et la gravité d'un tel scénario. Pour moi, l'approche la moins pénible mentalement est de se comporter comme si un tel scénario était garanti dans tous les cas - moins de réflexion.
Don Hatch le
5
@Ian Le problème est qu'il y a trop de bibliothèques qui modifient les prototypes d'objets. Il semble être une mauvaise idée de préconiser ce type de modèle alors que de bien meilleures alternatives simples existent, telles que Object.keys(target).forEach(key => { let value = target(key); /* Use key, value here */ });. Si vous devez montrer cette méthode, mentionnez au moins les risques et les meilleures alternatives pour ceux qui ne savent pas encore mieux.
Yona Appletree
8
Nous avons déjà es6 et TypeScript. Pourquoi le problème de l'écriture hasOwnProperty reste-t-il toujours non résolu? Même en 2017 et avec toute l'attention portée à JS. Je suis si déçu.
Gherman le
170

<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
la source
C'est la solution que je recherchais car elle me permettra de trier les clés avant l'itération
Andrew
Pour info, ceci n'est pas pris en charge sur le terrain de jeu TypeScript pour le moment.
Seanny123
1
Voir ici comment faire Object.entriesfonctionner dans TypeScript
Alex Klaus
C'est parfait
Piyush Choudhary
67

Que dis-tu de ça?

for (let [key, value] of Object.entries(obj)) {
    ...
}
Radon Rosborough
la source
1
Il nécessite la bibliothèque es2017 dans tsconfig. Voir stackoverflow.com/questions/45422573/…
Stéphane
C'est ce dont j'avais besoin pour surmonter l'erreur Typescript sur obj [key] "No index signature ..." car j'ai explicitement défini mon type d'obj comme {[key: string]: string} et je ne voulais pas utiliser {[key: chaîne]: n'importe quel}. Avec cela, je peux simplement accéder à la «valeur». Merci
ggedde
Et si vous voulez ignorer keytout, il suffit de laisser le champ vide: [ , value]. (Merci à ce commentaire .)
Dominik
51

Il y a une mise en garde à la boucle clé / valeur mentionnée par Ian. S'il est possible que les objets aient des attributs attachés à leur prototype, et lorsque vous utilisez lein opérateur, ces attributs seront inclus. Vous voudrez donc vous assurer que la clé est un attribut de votre instance et non du prototype. Les IE plus anciens sont connus pour s'être indexof(v)présentés comme une clé.

for (const key in myDictionary) {
    if (myDictionary.hasOwnProperty(key)) {
        let value = myDictionary[key];
    }
}
Jamie Starke
la source
3
N'essayez pas de couper les cheveux, mais puisque nous parlons de script de type, ne devriez-vous pas utiliser let key au lieu de var key? Belle réponse merci.
Luke Dupin
3
En fait, avec la version actuelle du script de type, keyet valuepeut être const.
Patrick Desjardins
Il est préférable de ne pas appeler la hasOwnPropertyvérification depuis l'objet cible, faites plutôt ceci: ...if (Object.prototype.hasOwnProperty.call(myDictionary, key))...Sinon, si vous utilisez eslint avec une no-prototype-builtinsrègle, il émettra une erreur.
séance du
6

Moyen le plus court pour obtenir toutes les valeurs de dictionnaire / objet:

Object.keys(dict).map(k => dict[k]);
k06a
la source
1

Pour obtenir les clés:

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

Ians Answer est bon, mais vous devriez utiliser const au lieu de let pour la clé car elle n'est jamais mise à jour.

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