2012-07-09 23 views
15

Estoy tratando de obtener una lista de todas las claves en una lista de diccionarios para completar el argumento de nombres de campo para csv.DictWriter.Extraer todas las claves de una lista de diccionarios

anteriormente, tenía algo como esto:

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

y yo estaba usando fieldnames = list[0].keys() a tomar el primer diccionario en la lista y extraer sus llaves.

Ahora tengo algo así como que uno de los diccionarios tiene más pares clave: valor que los demás (podría ser cualquiera de los resultados). Las nuevas claves se agregan dinámicamente en función de la información que proviene de una API, por lo que pueden aparecer o no en cada diccionario y no sé con anticipación cuántas claves nuevas habrá.

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

No puedo sólo tiene que utilizar fieldnames = list[1].keys() ya que no es necesariamente el segundo elemento que va a tener copias de las llaves.

Una solución sencilla sería encontrar el diccionario con el mayor número de teclas y utilizarla para los nombres de campo, pero eso no va a funcionar si usted tiene un ejemplo como este:

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

donde tanto el diccionario segunda y tercera tienen 3 llaves, pero el resultado final debería ser la lista ["name", "age", "height", "weight"]

Respuesta

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

Editar: tener que descomprimir la lista. Ahora arreglado.

+0

+1 comprensible y elegante –

+0

Probé esto como 'nombres de campo = set() Unión (d.keys() para d en allresults)' pero consiguieron una "TypeError: tipo insabrable: 'list'" – orh

+0

Funciona muy bien ahora, gracias – orh

2

el siguiente ejemplo se va a extraer las claves:

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

Sus datos:

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

Esta comprensión conjunto lo hará:

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

funciona de esta manera . En primer lugar, crear una lista de listas de las claves de diccionario:

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

A continuación, cree una versión aplanada de esta lista de listas:

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

Y crear un conjunto para eliminar duplicados:

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

Que se puede simplificar a:

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

Préstamo lis de la respuesta de @ AshwiniChaudhary, aquí hay una explicación de cómo podría resolver su problema.

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

iteración directamente sobre un diccionario devuelve sus llaves, por lo que no tiene que llamar keys() para recuperarlos, el ahorro de una llamada de función y una construcción de lista por cada elemento de la lista.

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

o utilizar itertools.chain:.

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