Combinar varios diccionarios de Python

5 minutos de lectura

avatar de usuario de jerrymouse
jerrymouse

Tengo que fusionar la lista del diccionario de python. Por ejemplo:

dicts[0] = {'a':1, 'b':2, 'c':3}
dicts[1] = {'a':1, 'd':2, 'c':'foo'}
dicts[2] = {'e':57,'c':3}

super_dict = {'a':[1], 'b':[2], 'c':[3,'foo'], 'd':[2], 'e':[57]}    

Escribí el siguiente código:

super_dict = {}
for d in dicts:
    for k, v in d.items():
        if super_dict.get(k) is None:
            super_dict[k] = []
        if v not in super_dict.get(k):
            super_dict[k].append(v)

¿Se puede presentar de forma más elegante/optimizada?

Nota
Encontré otra pregunta sobre SO, pero se trata de fusionar exactamente 2 diccionarios.

  • Ver también: combinar diccionario anidado

    – drftymac

    11 de diciembre de 2017 a las 21:03


  • Ver también: pregunta similar

    – drftymac

    11 de diciembre de 2017 a las 21:07

avatar de usuario de senderle
enviarle

Puede iterar sobre los diccionarios directamente, sin necesidad de usar range. los setdefault El método de dict busca una clave y devuelve el valor si lo encuentra. Si no se encuentra, devuelve un valor predeterminado y también asigna ese valor predeterminado a la clave.

super_dict = {}
for d in dicts:
    for k, v in d.iteritems():  # d.items() in Python 3+
        super_dict.setdefault(k, []).append(v)

Además, podría considerar el uso de un defaultdict. Esto solo automatiza setdefault llamando a una función para devolver un valor predeterminado cuando no se encuentra una clave.

import collections
super_dict = collections.defaultdict(list)
for d in dicts:
    for k, v in d.iteritems():  # d.items() in Python 3+
        super_dict[k].append(v)

Además, como observó astutamente Sven Marnach, parece que no desea duplicar valores en sus listas. En ese caso, set te consigue lo que quieres:

import collections
super_dict = collections.defaultdict(set)
for d in dicts:
    for k, v in d.iteritems():  # d.items() in Python 3+
        super_dict[k].add(v)

  • O si está buscando una sola línea, esto podría ayudar: stackoverflow.com/a/45649266/6568097

    – akhilsp

    27 de enero de 2020 a las 14:29

Avatar de usuario de Steven Rumbalski
Steven Rumbalski

from collections import defaultdict

dicts = [{'a':1, 'b':2, 'c':3},
         {'a':1, 'd':2, 'c':'foo'},
         {'e':57, 'c':3} ]

super_dict = defaultdict(set)  # uses set to avoid duplicates

for d in dicts:
    for k, v in d.items():  # use d.iteritems() in python 2
        super_dict[k].add(v)

  • +1: Esto parece ser exactamente lo que pedía la pregunta (elementos únicos en los valores), hecho de una manera relativamente clara y ciertamente eficiente (los diccionarios se revisan una sola vez y el conjunto incorporado hace que solo se mantengan elementos únicos rápido).

    – Eric O Lebigot

    18 de mayo de 2013 a las 8:19


Avatar de usuario de G_kuldeep
g_kuldeep

puedes usar este comportamiento de dict. (un poco elegante)

 a = {'a':1, 'b':2, 'c':3}
 b = {'d':1, 'e':2, 'f':3}
 c = {1:1, 2:2, 3:3}
 merge = {**a, **b, **c}
 print(merge) # {'a': 1, 'b': 2, 'c': 3, 'd': 1, 'e': 2, 'f': 3, 1: 1, 2: 2, 3: 3}

y eres bueno para ir 🙂

  • Su solución reemplaza los valores de las claves, en lugar de combinarlos en una lista. Este es el resultado de tu solución: {'a': 1, 'b': 2, 'c': 3, 'd': 2, 'e': 57}

    – TitanFighter

    24 sep 2019 a las 18:03

  • En mi caso, las claves eran únicas en cada dictado y esto era exactamente lo que quería. ¡Gracias!

    – akhilsp

    27 de enero de 2020 a las 14:33


  • este método elimina elementos duplicados en el diccionario.

    – Shah Vipul

    18 de febrero de 2021 a las 7:49

  • Pero, ¿cómo se hace en genérico para un número desconocido de diccionarios?

    – Ala M.

    28 de mayo de 2021 a las 11:54


  • ¿Hay alguna manera de hacer esto para una lista de diccionarios?

    – Trineo

    26 oct a las 19:34

Avatar de usuario de Sven Marnach
Sven Marnach

Combine las claves de todos los dictados y, para cada clave, ensamble la lista de valores:

super_dict = {}
for k in set(k for d in dicts for k in d):
    super_dict[k] = [d[k] for d in dicts if k in d]

La expresion set(k for d in dicts for k in d) construye un conjunto de todas las claves únicas de todos los diccionarios. Para cada una de estas claves únicas, usamos la lista de comprensión [d[k] for d in dicts if k in d] para construir la lista de valores de todos los dictados para esta clave.

Ya que solo pareces a uno el único valor de cada clave, es posible que desee utilizar conjuntos en su lugar:

super_dict = {}
for k in set(k for d in dicts for k in d):
    super_dict[k] = set(d[k] for d in dicts if k in d)

Parece que la mayoría de las respuestas que usan comprensiones no son tan legibles. En caso de que alguna se pierda en el lío de las respuestas anteriores, esto podría ser útil (aunque extremadamente tarde …). Simplemente recorra los elementos de cada dict y colóquelos en uno separado.

super_dict = {key:val for d in dicts for key,val in d.items()}

  • El OP quería ambos 'c' valores conservados: {'c':[3,'foo']}.

    –Steven Rumbalski

    21 de julio de 2016 a las 15:09

Avatar de usuario de Ramkrishan Sahu
Ramkrishan Sahu

Cuando el valor de las claves está en la lista:

from collections import defaultdict

    dicts = [{'a':[1], 'b':[2], 'c':[3]},
             {'a':[11], 'd':[2], 'c':['foo']},
             {'e':[57], 'c':[3], "a": [1]} ]

super_dict = defaultdict(list)  # uses set to avoid duplicates

for d in dicts:
    for k, v in d.items():  # use d.iteritems() in python 2
        super_dict[k] = list(set(super_dict[k] + v))

combined_dict = {}

for elem in super_dict.keys():
    combined_dict[elem] = super_dict[elem]

combined_dict
## output: {'a': [1, 11], 'b': [2], 'c': [3, 'foo'], 'd': [2], 'e': [57]}

  • El OP quería ambos 'c' valores conservados: {'c':[3,'foo']}.

    –Steven Rumbalski

    21 de julio de 2016 a las 15:09

Avatar de usuario de blQSheep
Ovejas

Tengo una solución muy fácil de usar sin ninguna importación. Yo uso el método dict.update(). Pero lamentablemente se sobrescribirá, si la misma clave aparece en más de un diccionario, entonces el valor del dict combinado más reciente aparecerá en la salida.

dict1 = {'Name': 'Zara', 'Age': 7}
dict2 = {'Sex': 'female' }
dict3 = {'Status': 'single', 'Age': 27}
dict4 = {'Occupation':'nurse', 'Wage': 3000}

def mergedict(*args):
    output = {}
    for arg in args:
        output.update(arg)
    return output
    
print(mergedict(dict1, dict2, dict3, dict4))

los producción Es esto:

{‘Nombre’: ‘Zara’, ‘Edad’: 27, ‘Sexo’: ‘femenino’, ‘Estado’: ‘soltero’, ‘Ocupación’: ‘enfermera’, ‘Salario’: 3000}

¿Ha sido útil esta solución?