web-dev-qa-db-fra.com

Comment fusionner des dictionnaires en Python?

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 est prioritaire s’il existe une clé en double.

84
TIMEX

Vous pouvez utiliser la méthode .update() si vous n'avez plus besoin du d2 original:

Mettez à jour le dictionnaire avec les paires clé/valeur des autres clés écrasant les clés existantes. Retourne 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 commencer par copier le dictionnaire afin de créer un nouveau dictionnaire fusionné. Cela peut ou peut ne pas être nécessaire. Si votre dictionnaire contient des objets composés (objets contenant d'autres objets, tels que des listes ou des instances de classe), copy.deepcopy doit également être pris en compte.

148
Felix Kling

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 annule d1:

dict(d1,**d2)
# {'a': 10, 'c': 3, 'b': 2}

Ce comportement n’est pas simplement un coup de chance de la mise en œuvre; il est garanti dans la documentation :

Si une clé est spécifiée à la fois dans le fichier argument positionnel et en tant que mot clé argument, la valeur associée à le mot clé est conservé dans le dictionnaire.

40
unutbu

Si vous souhaitez que d1 soit prioritaire dans les conflits, procédez comme suit:

d3 = d2.copy()
d3.update(d1)

Sinon, inversez d2 et d1.

14
tzot

Trey Hunner a publié un article dans le blog de Nice décrivant plusieurs options pour la fusion de plusieurs dictionnaires, notamment (pour python3.3 +) ChainMap et dictionary unpacking .

1
pfctdayelise

Ma solution est de définir une fonction merge . Ce n'est pas sophistiqué et ne coûte qu'une ligne. Voici le code dans 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 des arguments l'emporte.

1
Lei Zhao

Comme indiqué ci-dessus, je crois que l’utilisation de d2.update(d1) est la meilleure approche et que vous pouvez également copier d2 d’abord si vous en avez encore besoin.

Bien que, je tiens à souligner que dict(d1, **d2) est en fait un mauvais moyen de fusionner des dictionnaires en général puisque les arguments de mots clés doivent être des chaînes, donc cela échouera si vous avez une dict comme

{
  1: 'foo',
  2: 'bar'
}
0
Olivier Melançon