4

I have 4 dictionaries, let's call them:

dict1 , dict2 , dict3 , dict4

Example:

dict1 = {'A': 1, 'B':2}
dict2 = {'A': 3, 'C':4}
dict3 = {'B': 5, 'D':6}
dict4 = {'A': 7, 'B':8, 'C': 9, 'D':10, 'E':11}

Each dictionary level is "stronger" than those who come after it. As in, A found in dict1 will be 'stronger' than A found in dict2 in terms of precedence. Is there a short, elegant script to create a new dictionary, assembled from all four, where each key is taken from the "strongest" dictionary that contains that key?

The result should be: dict = {'A':1, 'B':2, 'C':4, 'D:6', 'E':11}

ballBreaker
  • 722
  • 1
  • 10
  • 29
Zusman
  • 606
  • 1
  • 7
  • 31
  • 1
    Some answers here can be adapted: https://stackoverflow.com/questions/38987/how-do-i-merge-two-dictionaries-in-a-single-expression – gorhawk Nov 20 '19 at 15:07
  • Related: [How do I merge a list of dicts into a single dict?](https://stackoverflow.com/q/3494906/7851470) – Georgy Nov 21 '19 at 15:13

4 Answers4

5

I think the easiest/clearest approach here would be to create a new dictionary then use its update method, which overwrites existing keys. Something like this makes the precedence pretty obvious:

>>> x = {}
>>> x.update(dict4)
>>> x.update(dict3)
>>> x.update(dict2)
>>> x.update(dict1)
>>> x
{'A': 1, 'B': 2, 'C': 4, 'D': 6, 'E': 11}

Docs

You could of course make a utility of some sort for this, something like:

>>> def collapse(*dicts):
...     x = {}
...     for dict in dicts:
...         x.update(dict)
...     return x
...
>>>
>>> collapse(dict4, dict3, dict2, dict1)
{'A': 1, 'B': 2, 'C': 4, 'D': 6, 'E': 11}

(Though you'd need to remember to pass the dictionaries in the correct order.)

chris
  • 1,915
  • 2
  • 13
  • 18
4

You could do the following (works on python 3.5 and newer):

result = {**dict4, **dict3, **dict2, **dict1}
Prebsus
  • 695
  • 9
  • 17
1

Here's a fairly simple way for an arbitrary number of dictionaries:

dict1 = {'A': 1, 'B':2}
dict2 = {'A': 3, 'C':4}
dict3 = {'B': 5, 'D':6}
dict4 = {'A': 7, 'B':8, 'C': 9, 'D':10, 'E':11}

# strongest dictionary last
dictionaries = [dict4, dict3, dict2, dict1]

dict(i for d in dictionaries for i in d.items())

Output:

{'A': 1, 'B': 2, 'C': 4, 'D': 6, 'E': 11}
Primusa
  • 13,136
  • 3
  • 33
  • 53
-1

You probably want a ChainMap, which is perfect for simulating scope.

>>> import collections
>>> cm = collections.ChainMap(dict1, dict2, dict3, dict4)
>>> dict(cm)
{'A': 1, 'B': 2, 'C': 4, 'D': 6, 'E': 11}
>>> cm['A'] = 'foo'
>>> cm
ChainMap({'A': 'foo', 'B': 2}, {'A': 3, 'C': 4}, {'B': 5, 'D': 6}, {'A': 7, 'B': 8, 'C': 9, 'D': 10, 'E': 11})
>>> dict1
{'A': 'foo', 'B': 2}
Peilonrayz
  • 3,129
  • 1
  • 25
  • 37