357

Say I have three dicts

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

How do I create a new d4 that combines these three dictionaries? i.e.:

d4={1:2,3:4,5:6,7:9,10:8,13:22}
codeforester
  • 39,467
  • 16
  • 112
  • 140
timy
  • 3,663
  • 4
  • 18
  • 8

5 Answers5

354
  1. Slowest and doesn't work in Python3: concatenate the items and call dict on the resulting list:

    $ 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. Fastest: exploit the dict constructor to the hilt, then one 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: a loop of update calls on an initially-empty dict:

    $ 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. Or, equivalently, one copy-ctor and two updates:

    $ 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
    

I recommend approach (2), and I particularly recommend avoiding (1) (which also takes up O(N) extra auxiliary memory for the concatenated list of items temporary data structure).

DiligentKarma
  • 5,198
  • 1
  • 30
  • 33
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 11
    I don't understand why `d4 = dict(d1, **dict(d2, **d3))` isn't faster than #2, but it isn't. – Robert Rossney Nov 23 '09 at 18:29
  • 15
    1 above is best if working on small dicts as it is clearer in my opinion. – Baz Feb 28 '12 at 20:13
  • 3
    Just stumbled on this thread and I am consistently getting ~0.2 usec faster results using `d4 = d1.copy(); d4.update(d2, **d3)` than `d4 = dict(d1, **d2); d4.update(d3)`. I know this is old but I thought I'd post my results. – Nolen Royalty Apr 04 '12 at 01:19
  • 47
    Unless all keys are known to be strings, option 2 is an abuse of a Python 2 implementation detail (the fact that some builtins implemented in C bypassed the expected checks on keyword arguments). In Python 3 (and in PyPy), option 2 will fail with non-string keys. – Carl Meyer Mar 30 '13 at 23:09
  • 2
    If you discount the time penalty of importing `itertools` it appears that `dict(itertools.chain(d1.items(), d2.items(), d3.items()))` is a contender as well. – ipmcc Jun 22 '16 at 10:24
  • 18
    I would add that `d1.items() + d2.items()` doesn't works in Python 3. – Francisco Jan 10 '17 at 17:00
  • 1
    Please update your answer, the first option won't work in Python3, which is what probably most people use by now. – imrek Apr 14 '17 at 08:25
  • 3
    This is very unreadable – UpmostScarab Jul 09 '17 at 10:39
  • 2
    What about dict comprehension? ```d1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}; d4={10:11,12:13}; d5={k:v for d in [d1,d2,d3,d4] for k,v in d.items()}``` Somehow I got: ```10000000 loops, best of 3: 0.0371 usec per loop``` while having almost the same computation time as the one shown above (Python 2.7.12 and Python 3.5.2) – j_s Nov 16 '17 at 21:05
  • @j_s dict comprehension works fastest for me as well, compared to the others listed in this answer, however, the looped dict update from another answer seems even faster: `d1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}; d4={}; d4={ d4.update(d) for d in [d1,d2,d3]}` – Gnudiff Nov 30 '17 at 11:52
  • 36
    In Python 3.5+ one can use the `**` notation: `d1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}; d4 = {**d1, **d2, **d3}`, which for me was nearly 3x faster than #3 or #4 above (0.228 usec per loop vs. 0.661 or 0.595 usec for #3 or 4, respectively). As mentioned above, #1 and #2 don't work on Python 3. – jared Apr 12 '18 at 04:14
  • what a lie - #2 perfectly works on python3: >python --version Python 3.6.4 >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)' 100000000 loops, best of 3: 0.011 usec per loop – Reishin Jun 02 '18 at 10:36
  • 1
    There is really no use in cluttering the answer space with `%%timeit` operations, just answer the question. – Nicolas Gervais Apr 24 '20 at 17:56
  • Option 2) does not work in Python 3. All other options are slower and less obvious than the _obvious_ solution from the comment right below the answer – which is IMHO the best answer – scravy Dec 21 '22 at 08:54
198

In python 2:

d4 = dict(d1.items() + d2.items() + d3.items())

In python 3 (and supposedly faster):

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

The previous SO question that both of these answers came from is here.

Benyamin Jafari
  • 27,880
  • 26
  • 135
  • 150
Amber
  • 507,862
  • 82
  • 626
  • 550
103

You can use the update() method to build a new dictionary containing all the items:

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

Or, in a loop:

dall = {}
for d in [d1, d2, d3]:
  dall.update(d)
sth
  • 222,467
  • 53
  • 283
  • 367
  • 4
    update does not build a new dictionary. It (as expected) updates the original one. – A.J.Rouvoet Feb 06 '13 at 17:30
  • 9
    @A.J.Rouvoet: "The original one" in this case is a brand new empty dictionary in `dall`. This new dictionary gets repeatedly updated to contain all the elements. It's intentional that `dall` is changed. – sth Feb 06 '13 at 17:38
  • 2
    Ah, my comment was purely on the way you phrased the first sentence. It suggested something that isn't the case. Although I admit a down vote may have been a bit harsh. – A.J.Rouvoet Feb 06 '13 at 22:09
  • logically using update we can create new dictionary by updating other and if we do not need the previous dic we can delete them using del d1 in for loop . – Jay Oct 29 '17 at 16:16
49

Here's a one-liner (imports don't count :) that can easily be generalized to concatenate N dictionaries:

Python 3

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

and:

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

Python 2.6 & 2.7

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

Output:

>>> 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}

Generalized to concatenate N dicts:

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

I'm a little late to this party, I know, but I hope this helps someone.

ron rothman
  • 17,348
  • 7
  • 41
  • 43
34

Use the dict constructor

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))

As a function

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

The overhead of creating intermediate dictionaries can be eliminated by using thedict.update() method:

from functools import reduce
def update(d, other): d.update(other); return d
d4 = reduce(update, (d1, d2, d3), {})
martineau
  • 119,623
  • 25
  • 170
  • 301