369 votes

comment concaténer deux dictionnaires pour en créer un nouveau en Python ?

Disons que j'ai trois dicts

d1={1:2,3:4}
d2={5:6,7:9}
d3={10:8,13:22}

Comment créer un nouveau d4 qui combine ces trois dictionnaires ? c'est-à-dire :

d4={1:2,3:4,5:6,7:9,10:8,13:22}

42 votes

D4 = {**d1, **d2, **d3} --> {1 : 2, 3 : 4, 5 : 6, 7 : 9, 10 : 8, 13 : 22}

362voto

Alex Martelli Points 330805
  1. le plus lent : concaténer les items et appeler dict sur la liste résultante :

    $ python -mtimeit -s'd1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}' \
    'd4 = dict(d1.items() + d2.items() + d3.items())'
    
    100000 loops, best of 3: 4.93 usec per loop
  2. le plus rapide : exploiter le dict à la poignée, puis un update :

    $ python -mtimeit -s'd1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}' \
    'd4 = dict(d1, **d2); d4.update(d3)'
    
    1000000 loops, best of 3: 1.88 usec per loop
  3. middling : une boucle de update appelle un dict initialement vide :

    $ python -mtimeit -s'd1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}' \
    'd4 = {}' 'for d in (d1, d2, d3): d4.update(d)'
    
    100000 loops, best of 3: 2.67 usec per loop
  4. ou, de manière équivalente, un vecteur de copie et deux mises à jour :

    $ python -mtimeit -s'd1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}' \
    'd4 = dict(d1)' 'for d in (d2, d3): d4.update(d)'
    
    100000 loops, best of 3: 2.65 usec per loop

Je recommande l'approche (2), et je recommande particulièrement d'éviter (1) (qui prend également O(N) de mémoire auxiliaire supplémentaire pour la structure de données temporaire de la liste concaténée des éléments).

12 votes

Je ne comprends pas pourquoi d4 = dict(d1, **dict(d2, **d3)) n'est pas plus rapide que le n°2, mais il ne l'est pas.

15 votes

Le point 1 ci-dessus est le meilleur si vous travaillez sur de petits dicts car il est plus clair à mon avis.

3 votes

Je viens de tomber sur ce fil de discussion et j'obtiens systématiquement des résultats plus rapides de ~0,2 usec en utilisant d4 = d1.copy(); d4.update(d2, **d3) que d4 = dict(d1, **d2); d4.update(d3) . Je sais que c'est vieux mais j'ai pensé que je devais poster mes résultats.

206voto

Amber Points 159296
d4 = dict(d1.items() + d2.items() + d3.items())

alternativement (et supposément plus rapide) :

d4 = dict(d1)
d4.update(d2)
d4.update(d3)

La question précédente de l'OS dont sont issues ces deux réponses est la suivante ici .

0 votes

Au lieu de d4 = dict(d1) on pourrait utiliser d4 = copy(d1) .

1 votes

@ds : Cela ne semble pas fonctionner. Peut-être vouliez-vous dire from copy import copy; d4 = copy(d1) ou peut-être d4 = d1.copy() .

45 votes

La première version ne fonctionne pas sur Python3.

106voto

sth Points 91594

Vous pouvez utiliser le update() pour construire un nouveau dictionnaire contenant tous les éléments :

dall = {}
dall.update(d1)
dall.update(d2)
dall.update(d3)

Ou, en boucle :

dall = {}
for d in [d1, d2, d3]:
  dall.update(d)

5 votes

La mise à jour ne construit pas un nouveau dictionnaire. Elle met à jour (comme prévu) le dictionnaire original.

10 votes

@A.J.Rouvoet : "L'original", dans ce cas, est un dictionnaire vide tout neuf dans dall . Ce nouveau dictionnaire est mis à jour de façon répétée pour contenir tous les éléments. C'est intentionnellement que dall est modifié.

2 votes

Ah, mon commentaire était purement sur la façon dont vous avez formulé la première phrase. Cela suggérait quelque chose qui n'est pas le cas. Bien que j'admette qu'un vote négatif aurait été un peu dur.

51voto

ron.rothman Points 2970

Voici un extrait ( imports ne comptent pas :) qui peut facilement être généralisé pour concaténer N dictionnaires, Python 2.6+ :

from itertools import chain
dict(chain.from_iterable(d.iteritems() for d in (d1, d2, d3))

Sortie :

>>> from itertools import chain
>>> d1={1:2,3:4}
>>> d2={5:6,7:9}
>>> d3={10:8,13:22}
>>> dict(chain.from_iterable(d.iteritems() for d in (d1, d2, d3)))
{1: 2, 3: 4, 5: 6, 7: 9, 10: 8, 13: 22}

Généralisé pour concaténer N dicts :

from itertools import chain
def dict_union(*args):
    return dict(chain.from_iterable(d.iteritems() for d in args))

Je suis un peu en retard à cette fête, je sais, mais j'espère que ça aidera quelqu'un.

4 votes

imports faire compte. mais la solution ici est toujours intéressante

0 votes

Pour python 3.6, ce devrait être d.items() au lieu de d.iteritems() . merci pour votre contribution !

0 votes

Juste un détail pour les perfectionnistes, la première version pour Python3 manque une parenthèse fermante.

34voto

Utilisez le constructeur dict

d1={1:2,3:4}
d2={5:6,7:9}
d3={10:8,13:22}

d4 = reduce(lambda x,y: dict(x, **y), (d1, d2, d3))

En fonction

from functools import partial
dict_merge = partial(reduce, lambda a,b: dict(a, **b))

La surcharge liée à la création de dictionnaires intermédiaires peut être éliminée en utilisant la fonction dict.update() méthode :

from functools import reduce
def update(d, other): d.update(other); return d
d4 = reduce(update, (d1, d2, d3), {})

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X