2012-07-09 3 views
15

J'essaie d'obtenir une liste de toutes les clés dans une liste de dictionnaires afin de remplir l'argument fieldnames pour csv.DictWriter.Extraire toutes les clés d'une liste de dictionnaires

précédemment, j'avais quelque chose comme ceci:

[ 
{"name": "Tom", "age": 10}, 
{"name": "Mark", "age": 5}, 
{"name": "Pam", "age": 7} 
] 

et j'utilisais fieldnames = list[0].keys() de prendre le premier dictionnaire dans la liste et en extraire les clés.

Maintenant, j'ai quelque chose comme ceci où l'un des dictionnaires a plus de paires clé-valeur que les autres (pourrait être l'un des résultats). Les nouvelles clés sont ajoutées dynamiquement en fonction des informations provenant d'une API, de sorte qu'elles peuvent apparaître ou non dans chaque dictionnaire et je ne sais pas à l'avance le nombre de nouvelles clés.

[ 
{"name": "Tom", "age": 10}, 
{"name": "Mark", "age": 5, "height":4}, 
{"name": "Pam", "age": 7} 
] 

Je ne peux pas utiliser fieldnames = list[1].keys() car il est pas nécessairement le deuxième élément qui aura des clés supplémentaires.

Une solution simple serait de trouver le dictionnaire le plus grand nombre de clés et de l'utiliser pour les noms des champs, mais cela ne fonctionnera pas si vous avez un exemple comme celui-ci:

[ 
{"name": "Tom", "age": 10}, 
{"name": "Mark", "age": 5, "height":4}, 
{"name": "Pam", "age": 7, "weight":90} 
] 

où les deux deuxième et troisième dictionnaire ont 3 clés, mais le résultat final devrait vraiment être la liste ["name", "age", "height", "weight"]

Répondre

29
all_keys = set().union(*(d.keys() for d in mylist)) 

Modifier: doivent déballer la liste. Maintenant corrigé.

+0

+1 compréhensible et élégante –

+0

J'ai essayé comme '= fieldnames set() union (d.keys() pour d en allresults)' mais a obtenu un "TypeError: type unchashable: 'list'" – orh

+0

Fonctionne très bien maintenant, merci – orh

2

L'exemple suivant va extraire les clés:

set_ = set() 
for dict_ in dictionaries: 
    set_.update(dict_.keys()) 
print set_ 
2
>>> lis=[ 
{"name": "Tom", "age": 10}, 
{"name": "Mark", "age": 5, "height":4}, 
{"name": "Pam", "age": 7, "weight":90} 
] 
>>> {z for y in (x.keys() for x in lis) for z in y} 
set(['age', 'name', 'weight', 'height']) 
10

Vos données:

>>> LoD 
[{'age': 10, 'name': 'Tom'}, 
{'age': 5, 'name': 'Mark', 'height': 4}, 
{'age': 7, 'name': 'Pam', 'weight': 90}] 

Cette compréhension de jeu va le faire:

>>> {k for d in LoD for k in d.keys()} 
{'age', 'name', 'weight', 'height'} 

Il fonctionne de cette façon . Tout d'abord, créer une liste de listes des clés dict:

>>> [list(d.keys()) for d in LoD] 
[['age', 'name'], ['age', 'name', 'height'], ['age', 'name', 'weight']] 

Ensuite, créez une version aplatie de cette liste de listes:

>>> [i for s in [d.keys() for d in LoD] for i in s] 
['age', 'name', 'age', 'name', 'height', 'age', 'name', 'weight'] 

Et créer un ensemble pour éliminer les doublons:

>>> set([i for s in [d.keys() for d in LoD] for i in s]) 
{'age', 'name', 'weight', 'height'} 

Ce qui peut être simplifié à:

{k for d in LoD for k in d.keys()} 
2

Empruntant lis de la réponse de @ AshwiniChaudhary, voici une explication de la façon dont vous pourriez résoudre votre problème.

>>> lis=[ 
{"name": "Tom", "age": 10}, 
{"name": "Mark", "age": 5, "height":4}, 
{"name": "Pam", "age": 7, "weight":90} 
] 

Itère directement sur une dict renvoie ses clés, de sorte que vous ne devez pas appeler keys() pour les récupérer, l'enregistrement d'un appel de fonction et une construction de liste par élément dans votre liste.

>>> {k for d in lis for k in d} 
set(['age', 'name', 'weight', 'height']) 

ou utilisez itertools.chain.

>>> from itertools import chain 
>>> {k for k in chain(*lis)} 
set(['age', 'name', 'weight', 'height']) 
Questions connexes