d3 = dict(d1, **d2)
Je comprends que cela fusionne le dictionnaire. Mais est-ce unique? Et si d1 a la même clé que d2 mais une valeur différente? Je voudrais que d1 et d2 soient fusionnés, mais d1 a la priorité s'il y a une clé en double.
d3 = dict(d1, **d2)
Je comprends que cela fusionne le dictionnaire. Mais est-ce unique? Et si d1 a la même clé que d2 mais une valeur différente? Je voudrais que d1 et d2 soient fusionnés, mais d1 a la priorité s'il y a une clé en double.
Réponses:
Vous pouvez utiliser la .update()
méthode si vous n'avez plus besoin de l'original d2
:
Mettez à jour le dictionnaire avec les paires clé / valeur d'autres clés , en écrasant les clés existantes . Retour
None
.
Par exemple:
>>> d1 = {'a': 1, 'b': 2}
>>> d2 = {'b': 1, 'c': 3}
>>> d2.update(d1)
>>> d2
{'a': 1, 'c': 3, 'b': 2}
Mettre à jour:
Bien sûr, vous pouvez d'abord copier le dictionnaire afin d'en créer un nouveau fusionné. Cela peut être nécessaire ou non. Dans le cas où vous avez des objets composés (objets qui contiennent d'autres objets, comme des listes ou des instances de classe) dans votre dictionnaire, copy.deepcopy
doivent également être pris en compte.
isinstance(int, object) is True
pourtant deepcopy
cela ne semble pas nécessaire.
En Python2,
d1={'a':1,'b':2}
d2={'a':10,'c':3}
d1 remplace d2:
dict(d2,**d1)
# {'a': 1, 'c': 3, 'b': 2}
d2 remplace d1:
dict(d1,**d2)
# {'a': 10, 'c': 3, 'b': 2}
Ce comportement n'est pas simplement un hasard de mise en œuvre; il est garanti dans la documentation :
Si une clé est spécifiée à la fois dans l'argument de position et en tant qu'argument de mot-clé, la valeur associée au mot-clé est conservée dans le dictionnaire.
**
notation, toutes les clés de ce dict doivent être des chaînes. Pour en savoir plus, consultez le fil de discussion python-dev à partir de mail.python.org/pipermail/python-dev/2010-April/099427.html .
d = dict(**d1, **d2)
marche, mais c'est ce que @IoannisFilippidis fait référence dans son commentaire. Peut-être que l'inclusion de l'extrait ici aurait été plus claire, alors la voici.
Ma solution est de définir une fonction de fusion . Ce n'est pas sophistiqué et ne coûte qu'une ligne. Voici le code 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()) }
Des tests
>>> 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()
{}
Cela fonctionne pour un nombre arbitraire d'arguments de dictionnaire. S'il y avait des clés en double dans ces dictionnaires, la clé du dictionnaire le plus à droite dans la liste d'arguments l'emporte.
.update
appel ( merged={}
suivi de for d in dict: merged.update(d)
) serait plus courte, plus lisible et plus efficace.
reduce
and lambda
s, qu'en est-il return reduce(lambda x, y: x.update(y) or x, dicts, {})
?
Trey Hunner a un joli article de blog décrivant plusieurs options pour fusionner plusieurs dictionnaires, y compris (pour python3.3 +) ChainMap et le déballage de dictionnaire .
À partir de Python 3.9
, l'opérateur |
crée un nouveau dictionnaire avec les clés et les valeurs fusionnées de deux dictionnaires:
# d1 = { 'a': 1, 'b': 2 }
# d2 = { 'b': 1, 'c': 3 }
d3 = d2 | d1
# d3: {'b': 2, 'c': 3, 'a': 1}
Ce:
Crée un nouveau dictionnaire d3 avec les clés et les valeurs fusionnées de d2 et d1. Les valeurs de d1 sont prioritaires lorsque d2 et d1 partagent des clés.
Notez également l' |=
opérateur qui modifie d2 en fusionnant d1 dans, avec priorité sur les valeurs d1:
# d1 = { 'a': 1, 'b': 2 }
# d2 = { 'b': 1, 'c': 3 }
d2 |= d1
# d2: {'b': 2, 'c': 3, 'a': 1}
Je pense que, comme indiqué ci-dessus, l'utilisation d2.update(d1)
est la meilleure approche et que vous pouvez également copierd2
premier si vous en avez encore besoin.
Cependant, je tiens à souligner que dict(d1, **d2)
c'est en fait une mauvaise façon de fusionner des dictionnaires en général, car les arguments de mot-clé doivent être des chaînes, donc cela échouera si vous avez un dict
tel que:
{
1: 'foo',
2: 'bar'
}
**
passage d'arguments de mot - clé à moins que toutes les clés ded2
soient des chaînes. Si toutes les clés de ned2
sont pas des chaînes, cela échoue dans Python 3.2 et dans des implémentations alternatives de Python telles que Jython, IronPython et PyPy. Voir, par exemple, mail.python.org/pipermail/python-dev/2010-April/099459.html .