A ChainMap
is a data structure in the collections module that allows for multiple mappings( mostly dictionaries) to be linked together and treated like a single unit.
In a single ChainMap
multiple dictionaries are connected in a chain-like manner. This allows for efficient lookup of values, since each dictionary is searched in turn, going from the first to the last. When a key is found in a dictionary, the corresponding value is returned and the search is terminated. If the key is not found in any of the dictionaries, an exception is raised.
The ChainMap
keeps references to the original dictionaries, this means that if any of the underlying dictionaries are modified, those changes will be reflected in the ChainMap
.
Instantiating ChainMaps
To create a ChainMap
, we start by importing the class from the collections module then use the following syntax.
ChainMap(*maps)
Where the parameter maps represents the arbitrary dict objects(or other mappings).
Create a ChainMap
#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)
Any modifications done to any of the linked dictionaries will be reflected in the ChainMap
.
#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)
d1['zero'] = 0
print(chain)
Retrieving data
Access the value associated with a key
When we access an element from the ChainMap
the element is looked up in the first map in the chain, if it is not found, then the lookup is continued in the next map in the chain (if any). This process continues until the element is found in one of the maps. If the element is not found in any of the maps, then just like in dictionaries, a KeyError
is raised.
#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'])
Just like in dictionaries we can use the get() method to access an element and specify a default value that will be returned in case the key does not exist in any of the linked dictionaries.
#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.get('two'))
print(chain.get('six'))
print(chain.get('seven'))
print(chain.get('ten', 'not found'))
ChainMap information
The ChainMap
class defines the items()
, keys()
, and values()
methods which returns the items, the keys and the values in the ChainMap
, respectively.
from collections import ChainMap
Europe = {'Germany': 'Berlin', 'France': 'Paris', 'Spain': 'Madrid'}
Africa = {'Nairobi': 'Kenya', 'Rwanda': 'Kigali', 'Nigeria': 'Abuja'}
Asia = {'Japan': 'Tokyo', 'China': 'Beijing', 'India': 'Delhi'}
chain = ChainMap(Europe, Africa, Asia)
print("items:")
print(chain.items(), '\n')
print("keys:")
print(chain.keys(), '\n')
print("values:")
print(chain.values(), '\n')
Inserting and Modifying data
The new_child() method adds a new dictionary at the beginning of the chain and returns a new ChainMap
reflecting the change.
from collections import ChainMap
Europe = {'Germany': 'Berlin', 'France': 'Paris', 'Spain': 'Madrid'}
Africa = {'Nairobi': 'Kenya', 'Rwanda': 'Kigali', 'Nigeria': 'Abuja'}
Asia = {'Japan': 'Tokyo', 'China': 'Beijing', 'India': 'Delhi'}
chain = ChainMap(Europe, Africa, Asia)
Americas = {'Canada': 'Ottawa', 'USA': 'Washington', 'Peru': 'Lima' }
updated_chain = chain.new_child(Americas)
print(updated_chain)
You can also insert single elements using the chain[key] = value
syntax.