for k, v in d.iteritems():
if type(v) is dict:
for t, c in v.iteritems():
print "{0} : {1}".format(t, c)
J'essaie de parcourir un dictionnaire et d'imprimer toutes les paires de valeurs clés où la valeur n'est pas un dictionnaire imbriqué. Si la valeur est un dictionnaire, je veux y entrer et imprimer ses paires de valeurs clés ... etc. De l'aide?
ÉDITER
Que dis-tu de ça? Il n'imprime toujours qu'une seule chose.
def printDict(d):
for k, v in d.iteritems():
if type(v) is dict:
printDict(v)
else:
print "{0} : {1}".format(k, v)
Cas de test complet
Dictionnaire:
{u'xml': {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'},
u'port': u'11'}}
Résultat:
xml : {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'}, u'port': u'11'}
python
dictionary
Takkun
la source
la source
dict
comme nom de variable. Ne faites jamais cela (c'est pourquoi cela échoue).Réponses:
Comme le dit Niklas, vous avez besoin de récursivité, c'est-à-dire que vous voulez définir une fonction pour imprimer votre dict, et si la valeur est un dict, vous voulez appeler votre fonction d'impression en utilisant ce nouveau dict.
Quelque chose comme :
la source
Il y a des problèmes potentiels si vous écrivez votre propre implémentation récursive ou l'équivalent itératif avec stack. Voir cet exemple:
Au sens normal, le dictionnaire imbriqué sera un arbre n-naire semblable à une structure de données. Mais la définition n'exclut pas la possibilité d'un bord croisé ou même d'un bord arrière (donc plus un arbre). Par exemple, ici key2.2 contient le dictionnaire à partir de key1 , key2.3 pointe vers le dictionnaire entier (bord arrière / cycle). Lorsqu'il y a un bord arrière (cycle), la pile / récursivité s'exécutera indéfiniment.
Si vous imprimez ce dictionnaire avec cette implémentation de Scharron
Vous verriez cette erreur:
Il en va de même avec l'implémentation de senderle .
De même, vous obtenez une boucle infinie avec cette implémentation de Fred Foo :
Cependant, Python détecte réellement les cycles dans le dictionnaire imbriqué:
"{...}" est l'endroit où un cycle est détecté.
Comme demandé par Moondra, c'est un moyen d'éviter les cycles (DFS):
la source
def myprint(d): stack = d.items() visited = set() while stack: k, v = stack.pop() if isinstance(v, dict): if k not in visited: stack.extend(v.iteritems()) else: print("%s: %s" % (k, v)) visited.add(k)
list(d.items())
commed.items()
renvoie une vue, pas une liste, et utiliser à lav.items()
place dev.iteritems()
Étant donné que a
dict
est itérable, vous pouvez appliquer la formule itérable classique des conteneurs imbriqués à ce problème avec seulement quelques modifications mineures. Voici une version de Python 2 (voir ci-dessous pour 3):Tester:
Dans Python 2, il peut être possible de créer une personnalisation
Mapping
qualifiée deMapping
mais ne contenant pasiteritems
, auquel cas cela échouera. Les documents n'indiquent pas queiteritems
c'est nécessaire pour unMapping
; d'autre part, la source donne auxMapping
types uneiteritems
méthode. Donc pour la coutumeMappings
, héritez decollections.Mapping
explicitement juste au cas où.Dans Python 3, il y a un certain nombre d'améliorations à apporter. Depuis Python 3.3, les classes de base abstraites vivent dans
collections.abc
. Ils restentcollections
également pour la compatibilité ascendante, mais il est plus agréable d'avoir nos classes de base abstraites ensemble dans un espace de noms. Donc, cela importeabc
decollections
. Python 3.3 ajoute égalementyield from
, qui est conçu uniquement pour ce genre de situations. Ce n'est pas du sucre syntaxique vide; cela peut conduire à un code plus rapide et à des interactions plus sensibles avec les coroutines .la source
isinstance(item, collections.Iterable)
n'est pas une garantie pourhasattr(item, "iteritems")
. Vérifier,collections.Mapping
c'est mieux.Iterable
rendrait cette solution plus généralisée, oubliant que, évidemment, les itérables ne l'ont pas forcémentiteritems
.yield from
syntaxe.Solution itérative alternative:
la source
list
) par unedeque
voire une file prioritaire.Version légèrement différente que j'ai écrite qui garde la trace des clés tout au long du chemin pour y arriver
Sur vos données, il s'imprimera
Il est également facile de le modifier pour suivre le préfixe comme un tuple de clés plutôt qu'une chaîne si vous en avez besoin de cette façon.
la source
Voici une façon pythonique de le faire. Cette fonction vous permettra de parcourir une paire clé-valeur dans tous les niveaux. Il ne sauvegarde pas le tout dans la mémoire mais parcourt le dict au fur et à mesure que vous le parcourez
Tirages
la source
Une solution alternative pour travailler avec des listes basées sur la solution Scharron
la source
Solution itérative comme alternative:
la source
O(depth)
pour la solution récursive. Il en va de même pour cette version, si je pense correctement).iters
comme une pile explicite, donc la consommation de mémoire Big-O est la même, ou est-ce que je manque quelque chose?J'utilise le code suivant pour imprimer toutes les valeurs d'un dictionnaire imbriqué, en tenant compte de l'endroit où la valeur pourrait être une liste contenant des dictionnaires. Cela m'a été utile lorsque j'ai analysé un fichier JSON dans un dictionnaire et que j'ai besoin de vérifier rapidement si l'une de ses valeurs l'est
None
.Production:
la source
Voici une version modifiée de la réponse de Fred Foo pour Python 2. Dans la réponse originale, seul le niveau le plus profond d'imbrication est affiché. Si vous sortez les clés sous forme de listes, vous pouvez conserver les clés pour tous les niveaux, bien que pour les référencer, vous devez référencer une liste de listes.
Voici la fonction:
Pour référencer les clés:
pour un dictionnaire à trois niveaux.
Vous devez connaître le nombre de niveaux avant d'accéder à plusieurs clés et le nombre de niveaux doit être constant (il est peut-être possible d'ajouter un petit morceau de script pour vérifier le nombre de niveaux d'imbrication lors de l'itération de valeurs, mais je ne l'ai pas fait encore regardé cela).
la source
Je trouve cette approche un peu plus flexible, ici vous fournissez simplement une fonction de générateur qui émet des paires clé, valeur et peut être facilement étendue pour itérer également sur des listes.
Ensuite, vous pouvez écrire votre propre
myprint
fonction, puis imprimer ces paires de valeurs clés.Un examen:
Production:
J'ai testé cela sur Python 3.6.
la source
Ces réponses ne fonctionnent que pour 2 niveaux de sous-dictionnaires. Pour en savoir plus, essayez ceci:
la source