Union of dict objects in Python


How do you calculate the union of two dict objects in Python, where a (key, value) pair is present in the result iff key is in either dict (unless there are duplicates)?

For example, the union of {'a' : 0, 'b' : 1} and {'c' : 2} is {'a' : 0, 'b' : 1, 'c' : 2}.

Preferably you can do this without modifying either input dict. Example of where this is useful: Get a dict of all variables currently in scope and their values

Asked By: Mechanical snail



This question provides an idiom. You use one of the dicts as keyword arguments to the dict() constructor:

dict(y, **x)

Duplicates are resolved in favor of the value in x; for example

dict({'a' : 'y[a]'}, **{'a', 'x[a]'}) == {'a' : 'x[a]'}
Answered By: Mechanical snail

You can also use update method of dict like

a = {'a' : 0, 'b' : 1}
b = {'c' : 2}

print a
Answered By: Nilesh

For a static dictionary, combining snapshots of other dicts:

As of Python 3.9, the binary "or" operator | has been defined to concatenate dictionaries. (A new, concrete dictionary is eagerly created):

>>> a = {"a":1}
>>> b = {"b":2}
>>> a|b
{'a': 1, 'b': 2}

Conversely, the |= augmented assignment has been implemented to mean the same as calling the update method:

>>> a = {"a":1}
>>> a |= {"b": 2}
>>> a
{'a': 1, 'b': 2}

For details, check PEP-584

Prior to Python 3.9, the simpler way to create a new dictionary is to create a new dictionary using the "star expansion" to add teh contents of each subctionary in place:

c = {**a, **b}

For dynamic dictionary combination, working as "view" to combined, live dicts:

If you need both dicts to remain independent, and updatable, you can create a single object that queries both dictionaries in its __getitem__ method (and implement get, __contains__ and other mapping method as you need them).

A minimalist example could be like this:

class UDict(object):
   def __init__(self, d1, d2):
       self.d1, self.d2 = d1, d2
   def __getitem__(self, item):
       if item in self.d1:
           return self.d1[item]
       return self.d2[item]

And it works:

>>> a = UDict({1:1}, {2:2})
>>> a[2]
>>> a[1]
>>> a[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in __getitem__
KeyError: 3

NB: If one wants to lazily maintain a Union "view" of two
or more dictionaries, check collections.ChainMap in the standard library – as it has all dictionary methods and cover corner cases not
contemplated in the example above.

Answered By: jsbueno

Two dictionaries

def union2(dict1, dict2):
    return dict(list(dict1.items()) + list(dict2.items()))

n dictionaries

def union(*dicts):
    return dict(itertools.chain.from_iterable(dct.items() for dct in dicts))
Answered By: Mathieu Larose