Python Forum
ChainMaps - Chaining multiple dictionaries
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ChainMaps - Chaining multiple dictionaries
#1
The collections module in the standard library provides the ChainMap class which joins multiple dictionaries to act as if it was a one large dictionary.
Consider the following example:
#import the ChainMap class
from collections import ChainMap

d1 = {'one': 1, 'two': 2, 'three': 3}
d2 = {'four': 4, 'five': 5, 'six': 6}
d3 = {'seven': 7, 'eight': 8, 'nine': 9}

chain = ChainMap(d1, d2, d3)

print(chain)
Output:
ChainMap({'one': 1, 'two': 2, 'three': 3}, {'four': 4, 'five': 5, 'six': 6}, {'seven': 7, 'eight': 8, 'nine': 9})
The resulting ChainMap object has a dictionary interface. When retrieving data, each dictionary is searched in turn, going from the first to the last.
#import the ChainMap class
from collections import ChainMap

d1 = {'one': 1, 'two': 2, 'three': 3}
d2 = {'four': 4, 'five': 5, 'six': 6}
d3 = {'seven': 7, 'eight': 8, 'nine': 9}

chain = ChainMap(d1, d2, d3)

print(chain['three'])
print(chain['five'])
print(chain['eight'])
print(chain['nine'])
Output:
3 5 8 9
As shown chainmap object acts as if it was a one long dictionary made from the individual dictionaries.
See More:
Reply
#2
Thanks, interesting feature though I suspect it doesn't happen often, when one needs such an "aggregator". It would be luck to recollect about it in time :)

Also it is curious to investigate behavior of duplicate keys and key removal and reinserting

from collections import ChainMap

d1 = {'one': 1, 'two': 2, 'three': 3}
d2 = {'four': 4, 'five': 5, 'six': 6, 'three': 'drei'}
d3 = {'seven': 7, 'eight': 8, 'nine': 9}

chain = ChainMap(d1, d2, d3)

print(chain['three'])
print(chain['five'])
print(chain['eight'])
print(chain['nine'])
del chain['three']
print('three' in d1, 'three' in d2)
print(chain['three'])
chain['three'] = 'trois'
print('three' in d1, 'three' in d2)
it could be seen that insert works into the first dict, while duplicates simply shadow each other

P.S. now a kind of homework: how iteration over keys works? in which order? what if there are duplicates?
maina likes this post
Reply
#3
(Jun-23-2024, 05:48 AM)rodiongork Wrote: I suspect it doesn't happen often, when one needs such an "aggregator".
This can be useful when you want to alter temporarily a context, then restore the initial context. For example suppose that you are writing something on a sheet of paper and the context contains the color of the pen, initialy black and its width, initialy 1.
>>> def write(*args): # for illustrative purpose
...     pass
... 
>>> from collections import ChainMap
>>> c = ChainMap({'width': 1, 'color': 'black'}) # initial context
>>> write('Hello world!', c) # write something 
>>> 
>>> c = c.new_child({'color': 'red'})  # temporarily set the color
>>> c['color']
'red'
>>> write('Nice weather today!', c) # write in red
>>> c = c.parents # restore previous context
>>> c['color']
'black'
This usage is similar to the operators gsave and grestore in the Postscript language. gsave saves the current « graphic context » which contains various parameters. Then one can update the context temporarily, and the next call to grestore restores the initial graphic context.

(Jun-23-2024, 05:48 AM)rodiongork Wrote: now a kind of homework: how iteration over keys works? in which order? what if there are duplicates?
Hint: start by reading the code of collections/__init__.py
maina and DeaD_EyE like this post
« We can solve any problem by introducing an extra level of indirection »
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020