Skip to content Skip to sidebar Skip to footer

Dict Merge In A Dict Comprehension

In python 3.5, we can merge dicts by using double-splat unpacking >>> d1 = {1: 'one', 2: 'two'} >>> d2 = {3: 'three'} >>> {**d1, **d2} {1: 'one', 2: 'two

Solution 1:

It's not exactly an answer to your question but I'd consider using ChainMap to be an idiomatic and elegant way to do what you propose (merging dictionaries in-line):

>>>from collections import ChainMap>>>d1 = {1: 'one', 2: 'two'}>>>d2 = {3: 'three'}>>>ds = [d1, d2]>>>dict(ChainMap(*ds))
{1: 'one', 2: 'two', 3: 'three'}

Although it's not a particularly transparent solution, since many programmers might not know exactly how a ChainMap works. Note that (as @AnttiHaapala points out) "first found is used" so, depending on your intentions you might need to make a call to reversed before passing your dicts into ChainMap.

>>> d2 = {3: 'three', 2: 'LOL'}
>>> ds = [d1, d2]
>>> dict(ChainMap(*ds))
{1: 'one', 2: 'two', 3: 'three'}

>>> dict(ChainMap(*reversed(ds)))
{1: 'one', 2: 'LOL', 3: 'three'}

Solution 2:

To me, the obvious way is:

d_out = {}
for d in ds:
    d_out.update(d)

This is quick and probably quite performant. I don't know that I can speak for the python developers, but I don't know that your expected version is more easy to read. For example, your comprehension looks more like a set-comprehension to me due to the lack of a :. FWIW, I don't think there is any technical reason (e.g. parser ambiguity) that they couldn't add that form of comprehension unpacking.

Apparently, these forms were proposed, but didn't have universal enough support to warrant implementing them (yet).

Solution 3:

You could use itertools.chain or itertools.chain.from_iterable:

import itertools

ds = [{'a': 1, 'b': 2}, {'c': 30, 'b': 40}]

merged_d = dict(itertools.chain(*(d.items() for d in ds)))
print(merged_d)  # {'a': 1, 'b': 40, 'c': 30}

Solution 4:

You could define this function:

from collections import ChainMap
defmergeDicts(l):
    returndict(ChainMap(*reversed(list(l))))

You can then use it like this:

>>>d1 = {1: 'one', 2: 'two'}>>>d2 = {3: 'three'}>>>ds = [d1, d2]>>>mergeDicts(ds)
{1: 'one', 2: 'two', 3: 'three'}

Solution 5:

Based on this solution and also mentioned by @ilgia-everilä, but making it Py2 compatible and still avoiding intermediate structures. Encapsulating it inside a function makes its use quite readable.

defmerge_dicts(*dicts, **extra):
    """
    >>> merge_dicts(dict(a=1, b=1), dict(b=2, c=2), dict(c=3, d=3), d=4, e=4)
    {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 4}
    """returndict((
        (k,v)
        for d in dicts
        for k,v in d.items()
    ), **extra)

Post a Comment for "Dict Merge In A Dict Comprehension"