¿Cómo fusiono una lista de dictados en un solo dictado?

124

¿Cómo puedo convertir una lista de dictados como este?

[{'a':1}, {'b':2}, {'c':1}, {'d':2}]

En un solo dictado como este

{'a':1, 'b':2, 'c':1, 'd':2}
horno
fuente
Es cierto, aunque eso se funde en un dictado de listas.
Katriel
1
es una lista y no un dict: >>> type ([{'a': 1}, {'b': 2}]) <type 'list'>
killown
Realmente debería haber una sola línea para esto considerando la frecuencia con la que aparece. ¿Hay alguna razón por la que no se admite {** d para d en d_list}?
Markemus

Respuestas:

163

Esto funciona para diccionarios de cualquier longitud:

>>> result = {}
>>> for d in L:
...    result.update(d)
... 
>>> result
{'a':1,'c':1,'b':2,'d':2}

Como comprensión :

# Python >= 2.7
{k: v for d in L for k, v in d.items()}

# Python < 2.7
dict(pair for d in L for pair in d.items())
wim
fuente
6
>>> L=[{'a': 1}, {'b': 2}, {'c': 1}, {'d': 2}]    
>>> dict(i.items()[0] for i in L)
{'a': 1, 'c': 1, 'b': 2, 'd': 2}

Nota: el orden de 'b' y 'c' no coincide con su salida porque los dictados están desordenados

si los dictados pueden tener más de una clave / valor

>>> dict(j for i in L for j in i.items())
John La Rooy
fuente
Falla si alguno de los dictados de la lista tiene más de un elemento.
PaulMcG
2
tos * (asumiendo que cada diccionario contiene solo un par clave-valor) * tos
Katriel
Ah, bueno, primero publiqué un método que funciona con dictados generales, pero parecía que el OP no necesitaba eso
John La Rooy
5

Para los diccionarios planos, puede hacer esto:

from functools import reduce
reduce(lambda a, b: dict(a, **b), list_of_dicts)
dietbuddha
fuente
4

Esto es similar a @delnan pero ofrece la opción de modificar los elementos k / v (clave / valor) y creo que es más legible:

new_dict = {k:v for list_item in list_of_dicts for (k,v) in list_item.items()}

por ejemplo, reemplace k / v elems de la siguiente manera:

new_dict = {str(k).replace(" ","_"):v for list_item in list_of_dicts for (k,v) in list_item.items()}

desempaqueta la tupla k, v del generador de diccionario .items () después de sacar el objeto dict de la lista

Schalton
fuente
2
dict1.update( dict2 )

Esto es asimétrico porque debe elegir qué hacer con las claves duplicadas; en este caso, dict2sobrescribirá dict1. Cámbielos por el otro lado.

EDITAR: Ah, lo siento, no vi eso.

Es posible hacer esto en una sola expresión:

>>> from itertools import chain
>>> dict( chain( *map( dict.items, theDicts ) ) )
{'a': 1, 'c': 1, 'b': 2, 'd': 2}

¡No tengo crédito por esto último!

Sin embargo, yo diría que podría ser más Pythonic (explícito> implícito, plano> anidado) hacer esto con un forbucle simple . YMMV.

Katriel
fuente
1
es una lista y no un dictado: >>> tipo ([{'a': 1}, {'b': 2}]) <tipo 'lista'>
killown
1

Puede utilizar unirse a la función de funcy biblioteca:

from funcy import join
join(list_of_dicts)
Suor
fuente
1

Poca mejora para la respuesta de @dietbuddha con el desempaquetado de diccionario de PEP 448 , para mí, es más legible de esta manera, y también es más rápido :

from functools import reduce
result_dict = reduce(lambda a, b: {**a, **b}, list_of_dicts)

Pero tenga en cuenta que esto solo funciona con las versiones de Python 3.5+.

Insomnec631
fuente
0
>>> dictlist = [{'a':1},{'b':2},{'c':1},{'d':2, 'e':3}]
>>> dict(kv for d in dictlist for kv in d.iteritems())
{'a': 1, 'c': 1, 'b': 2, 'e': 3, 'd': 2}
>>>

Tenga en cuenta que agregué un segundo par clave / valor al último diccionario para mostrar que funciona con múltiples entradas. Además, las claves de los dictados posteriores en la lista sobrescribirán la misma clave de un dictado anterior.

Dave Kirby
fuente
-1

dic1 = {'María': 12, 'Paco': 22, 'José': 23} dic2 = {'Patricia': 25, 'Marcos': 22 'Tomas': 36}

dic2 = dict (dic1.items () + dic2.items ())

y este será el resultado:

dic2 {'José': 23, 'Marcos': 22, 'Patricia': 25, 'Tomas': 36, 'Paco': 22, 'María': 12}

Max Herrera
fuente