Comment fusionner deux dictionnaires en Python 2 et 3

  1. Fusion de dictionnaires Python 2.7
  2. Méthode de fusion de dictionnaire Python 3.5 (et plus)
  3. Conclusion sur les méthodes de fusion

Supposons que nous ayons deux dictionnaires A et B à fusionner, où les valeurs dans B remplaceront les valeurs dans A si elles partagent la même key.

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}

L’objet Python dictionnaire a une méthode instrinsèque update() pour mettre à jour le dictionnaire A avec B,

A.update(B)

Mais les données de A seront remplacées à la place au lieu de retourner un nouveau dictionnaire contenant la fusion de A et B.

Nous allons présenter les méthodes de fusion de deux dictionnaires et de retour d’un nouveau dictionnaire.

Fusion de dictionnaires Python 2.7

Méthode de compréhension du dictionnaire - 1

C = {key: value for d in (A, B) for key, value in d.items()}

d.itmes() renvoie une liste de paires (clé, valeur) comme 2-tuples du dictionnaire d.

Cette méthode utilise la compréhension des dictionnaires imbriqués pour fusionner deux dictionnaires. Le bon ordre de for doit être pris en compte. Il devrait l’être,

flattern_patterns = [planet
                    for sublist in planets
                    for planet in sublist]

Méthode de compréhension du dictionnaire - 2

Nous pourrions aussi utiliser la méthode dict() pour initialiser le nouveau dictionnaire.

C = dict((key, value) for d in (A, B) for key, value in d.items())

Techniquement parlant, elle est presque la même que la méthode ci-dessus mais diffère dans les performances qui seront mentionnées par la suite.

Méthode itertools.chain

Le module itertools standardise un ensemble de blocs de construction iterator. Il a des caractéristiques comme la rapidité et l’efficacité de la mémoire.

itertools.chain renvoie un objet chaîne dont la méthode .next() renvoie les éléments du premier itérable jusqu’à ce qu’il soit épuisé, puis le(s) itérable(s) suivant(s), jusqu’à ce que tous soient épuisés.

dict(itertools.chain(A.iteritems(), B.iteritems()))

iteritems() renvoie un itérateur sur les éléments (key, value) du dictionnaire.

Par conséquent, les scripts ci-dessus retourneront un dictionnaire contenant les éléments de A et B.

Méthode copy et update

Comme mentionné au début, update() pourrait fusionner A et B, mais remplacera le dictionnaire en place. Nous pourrions utiliser la méthode copy() pour faire une copie du dictionnaire A.

m = A.copy()
C = m.update(B)

Fusionner les méthodes Analyse et comparaison des performances

import timeit

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}

SETUP_CODE = '''
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''

TEST_CODE = '''
{key: value for d in (A, B) for key, value in d.items()}
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))

TEST_CODE = '''
dict((key, value) for d in (A, B) for key, value in d.items())
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))

TEST_CODE = '''
dict(itertools.chain(A.iteritems(), B.iteritems()))
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))

SETUP_CODE = '''
def merge_dicts(a, b):
    m = a.copy()
    m.update(b)
    return m

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''

TEST_CODE = '''
merge_dicts(A, B)
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))

Le résultat est

0.0162378
0.029774
0.019975
0.0110059
Méthode Performance Classement
{key: value for d in (A, B) for key, value in d.items()} 0.0162378 2
dict((key, value) for d in (A, B) for key, value in d.items()) 0.029774 4
dict(itertools.chain(A.iteritems(), B.iteritems())) 0.019975 3
merge_dicts(a, b) 0.0110059 1

Méthode de fusion de dictionnaire Python 3.5 (et plus)

A partir de Python 3.5, en plus des mêmes méthodes que dans Python 2.7, il a aussi l’opérateur de décompactage ** de dictionary, comme introduit dans PEP-448. Il permet de décompresser un nombre arbitraire d’éléments.

Attention

d.iteritems() devient obsolète en Python 3. Voir PEP-469

>>> C = {**A, **B}
>>> C
{'x': 10, 'y': 30, 'z': 40}
import timeit

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}

SETUP_CODE = '''
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''

TEST_CODE = '''
{**A, **B}
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))

TEST_CODE = '''
{key: value for d in (A, B) for key, value in d.items()}
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))

TEST_CODE = '''
dict((key, value) for d in (A, B) for key, value in d.items())
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))

TEST_CODE = '''
dict(itertools.chain(A.items(), B.items()))
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))

SETUP_CODE = '''
def merge_dicts(a, b):
    m = a.copy()
    m.update(b)
    return m

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''

TEST_CODE = '''
merge_dicts(A, B)
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))
0.0017047999999999508
0.009127499999999955
0.0168952
0.01078009999999996
0.005767999999999995
Méthode Performance Classement
{**A, **B} 0.0017047999999999508 1
{key: value for d in (A, B) for key, value in d.items()} 0.009127499999999955 3
dict((key, value) for d in (A, B) for key, value in d.items()) 0.0168952 5
dict(itertools.chain(A.items(), B.items())) 0.01078009999999996 4
merge_dicts(a, b) 0.005767999999999995 2

Conclusion sur les méthodes de fusion

En Python 2.7, copy et update est la meilleure méthode.

m = A.copy()
C = m.update(B)

En Python 3.5+, la méthode de déballage du dictionnaire est la meilleure.

{**A, **B}

Article connexe - Python dictionary

  • Comment retirer un élément d'un dictionnaire Python