d3 = dict(d1, **d2)
Entiendo que esto fusiona el diccionario. Pero, ¿es único? ¿Qué pasa si d1 tiene la misma clave que d2 pero un valor diferente? Me gustaría que d1 y d2 se fusionen, pero d1 tiene prioridad si hay una clave duplicada.
d3 = dict(d1, **d2)
Entiendo que esto fusiona el diccionario. Pero, ¿es único? ¿Qué pasa si d1 tiene la misma clave que d2 pero un valor diferente? Me gustaría que d1 y d2 se fusionen, pero d1 tiene prioridad si hay una clave duplicada.
Respuestas:
Puede utilizar el .update()método si ya no necesita el original d2:
Actualice el diccionario con los pares clave / valor de otros, sobrescribiendo las claves existentes . Regreso
None.
P.ej:
>>> d1 = {'a': 1, 'b': 2}
>>> d2 = {'b': 1, 'c': 3}
>>> d2.update(d1)
>>> d2
{'a': 1, 'c': 3, 'b': 2}
Actualizar:
Por supuesto, puede copiar el diccionario primero para crear uno nuevo combinado. Esto puede ser necesario o no. En caso de que tenga objetos compuestos (objetos que contienen otros objetos, como listas o instancias de clase) en su diccionario, copy.deepcopytambién debe considerarse.
isinstance(int, object) is Truepero deepcopyno parece necesario.
En Python2,
d1={'a':1,'b':2}
d2={'a':10,'c':3}
d1 anula d2:
dict(d2,**d1)
# {'a': 1, 'c': 3, 'b': 2}
d2 anula d1:
dict(d1,**d2)
# {'a': 10, 'c': 3, 'b': 2}
Este comportamiento no es solo una casualidad de implementación; está garantizado en la documentación :
Si se especifica una clave tanto en el argumento posicional como en el argumento de palabra clave, el valor asociado con la palabra clave se conserva en el diccionario.
**notación, todas las claves de ese dictado deben ser cadenas. Consulte el hilo de python-dev que comienza en mail.python.org/pipermail/python-dev/2010-April/099427.html para obtener más información.
d = dict(**d1, **d2)funciona, pero eso es lo que @IoannisFilippidis hace referencia en su comentario. Quizás incluir el fragmento aquí hubiera sido más claro, así que aquí está.
Mi solución es definir una función de combinación . No es sofisticado y solo cuesta una línea. Aquí está el código en Python 3.
from functools import reduce
from operator import or_
def merge(*dicts):
return { k: reduce(lambda d, x: x.get(k, d), dicts, None) for k in reduce(or_, map(lambda x: x.keys(), dicts), set()) }
Pruebas
>>> d = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> d_letters = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d, d_letters)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d_letters, d)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> merge(d_letters)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge()
{}
Funciona para un número arbitrario de argumentos de diccionario. Si hubiera claves duplicadas en ese diccionario, gana la clave del diccionario situado más a la derecha en la lista de argumentos.
.updatellamada en él ( merged={}seguido de for d in dict: merged.update(d)) sería más corto, más legible y más eficiente.
reducey lambdaS, ¿qué tal return reduce(lambda x, y: x.update(y) or x, dicts, {})?
Trey Hunner tiene una buena publicación de blog que describe varias opciones para combinar varios diccionarios, incluido (para python3.3 +) ChainMap y desempaquetado de diccionarios .
Comenzando Python 3.9, el operador |crea un nuevo diccionario con las claves y valores combinados de dos diccionarios:
# d1 = { 'a': 1, 'b': 2 }
# d2 = { 'b': 1, 'c': 3 }
d3 = d2 | d1
# d3: {'b': 2, 'c': 3, 'a': 1}
Esta:
Crea un nuevo diccionario d3 con las claves y valores combinados de d2 y d1. Los valores de d1 tienen prioridad cuando d2 y d1 comparten claves.
También tenga en cuenta el |=operador que modifica d2 fusionando d1 en, con prioridad en los valores de d1:
# d1 = { 'a': 1, 'b': 2 }
# d2 = { 'b': 1, 'c': 3 }
d2 |= d1
# d2: {'b': 2, 'c': 3, 'a': 1}
Creo que, como se indicó anteriormente, usar d2.update(d1)es el mejor enfoque y que también puede copiar d2primero si aún lo necesita.
Aunque, quiero señalar que en dict(d1, **d2)realidad es una mala manera de fusionar diccionarios en general, ya que los argumentos de palabras clave deben ser cadenas, por lo que fallará si tiene una dictcomo:
{
1: 'foo',
2: 'bar'
}
**paso de argumentos de palabras clave, a menos que todas las claves ded2sean cadenas. Si no todas las claves ded2son cadenas, esto falla en Python 3.2 y en implementaciones alternativas de Python como Jython, IronPython y PyPy. Consulte, por ejemplo, mail.python.org/pipermail/python-dev/2010-April/099459.html .