web-dev-qa-db-fra.com

python - liste itérative des dictionnaires et déballage

Étant donné une liste plate de dictionnaires simples

lst = [{'key1': 1}, {'key2': 2}, {'key3': 3}]

Je voudrais trouver le dict qui donne la valeur minimale évaluée en utilisant une méthode non détaillée ici. Ma première idée a été d'itérer la liste pour vérifier dict par dict, mais cela échoue:

for k, v in [x.items() for x in lst]:
    print(k, v)

résultats ValueError (ainsi qu'en utilisant un générateur au lieu de la liste):

for k, v in [x.items() for x in lst]:
ValueError: not enough values to unpack (expected 2, got 1)

Cependant,

for x in lst:
    for k, v in x.items():
        print(k, v)

les rendements

key1 1
key2 2
key3 3

Comme prévu. Je suppose que toutes les approches fonctionnent comme prévu (sauf PEBKAC), mais pourquoi cela ne fonctionne-t-il pas en utilisant la compréhension de la liste? Quelqu'un pourrait-il m'éclairer?

Edit: j'utilise python 3 et je sais que items () donne un dict_view mais je ne vois pas pourquoi la logique ne fonctionne pas.

13
jake77

Vous manquez un niveau d'itération.

Normalement, les dict ont plus d'une paire clé/valeur. dict.items() convertit le dictionnaire entier en une séquence de tuples sous la forme (key, value). Dans votre cas, chaque dictionnaire a un seul élément, mais le résultat de items() est toujours un Tuple de tuples.

Si vous imprimez le résultat de [x.items() for x in lst] vous verrez que le résultat est une liste d'éléments dict_view; chacun de ceux-ci peut lui-même être itéré.

7
Daniel Roseman

Au lieu de prendre le premier élément de votre dict_view vous pouvez ajouter un niveau d'indentation (comme l'a suggéré @DanielRoseman) dans votre compréhension de liste:

for k, v in [(k, v) for x in lst for (k, v) in x.items()]:
  print(k, v)

rendement

key1 1
key2 2
key3 3

comme prévu.

4
Kruupös

Essayez de décompresser votre lst étape par étape pour comprendre comment il est construit.

>>> in: lst[0].items()
>>> out: [('key1', 1)]

Votre résultat (qui est égal à votre expression x.items() dans la compréhension de la liste) est ne autre liste contenant votre Tuple de k et v. Le Tuple est l'élément d'index 0 dans cette liste (et aussi le seul élément du tout). Vous devez donc aller comme

for k, v in [x.items()[0] for x in lst]:
    print(k, v)
1
offeltoffel

Vous pouvez parcourir la paire clé/valeur d'un dictionnaire comme ceci: -

for k, v in dic.items():
    print(k, v)

ce que le code ci-dessus fait est de convertir d'abord le dictionnaire en une liste de tuples qui sont ensuite décompressés un par un tout en itérant en k, v comme: -

k, v = (k, v) # Tuple unpacking.

Maintenant, dans votre cas, considérez ce code: -

z = [x.items() for x in lst]
print(z)

La sortie est

[dict_items([('key1', 1)]), dict_items([('key2', 2)]), dict_items([('key3', 3)])] 

soit un liste de listes de Tuple.

Alors, réécrivons votre code comme: -

for k, v in z:
    print(k, v)

Où z est une liste de listes de Tuple. A chaque itération, il récupère une liste (qui ne contient qu'un seul élément) dans la liste parent puis il essaie: -

k, v = [(key, value)] # a list of only one Tuple to be unpacked against two variables and hence the failure.

J'espère que cela a été utile.

0
gautamaggarwal