Multi-key combinations to access values
a) Table/matrix representation using tupels
Tupels are 'hashable' objects and hence can be used as a key in python dictionaries.
{(key_part_1, key_part_2): value}
Example
d={}
d[('Antje','place')]='Barcelona'
d[('Antje','year')]='1987'
d[('Mike','place')]='Berlin'
key=('Antje','year')
if key in d:
print( d[key] )
1987
# Problem: when key-pair does not exist: key error for missing entries
print( d[('Mike','year')] )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: ('Mikes', 'year')
# Solution: provide values for all key-pairs (a), or use sparse nested dictionary (b)
b) Sparse matrix or tree like representation using dict in dict
# Nested dictionaries in python
from collections import defaultdict
d = defaultdict(dict)
d['Antje']['place']='Barcelona'
d['Antje']['year']='1987'
defaultdict(<type 'dict'>, {'Antje': {'place': 'Barcelona', 'year': '1987'}})
d['Mike']['place']='Berlin'
# print if key pair exist
keyA='Antje'
keyB='year'
if ( keyA in d ) & ( keyB in d[keyA] ):
print( d[keyA][keyB] )
1987
# key error for missing entried
print( d['Mike']['year'] )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'year'
# use get, to print default value if second key ('year') is missing
print( d['Mike'].get('year', 'NaN') )
NaN
# check if both key's are present
if 'year' in d.get('Antje', {}):
print( d['Antje']['year'] )
# check if second key is present
if d['Antje'].get('year', False):
print( d['Antje']['year'] )
# check if first key is present
'Mike' in d
True
# get all first level keys
sorted(d.keys())
['Antje', 'Mike']
# get second level keys of selected first level key 'Mike'
sorted([ k for k in d['Mike'] ])
['place']
# get all possible second level keys of all first level keys together (set comprehension)
sorted(list({k2 for v in d.values() for k2 in v}))
['place', 'year']
# get values of all second keys of a first key identifier (name)
name='Antje'
[ d[name][k] for k in d[name] ]
['Barcelona', '1987']
# get all possible values of a selected second key: 'place' or 'year' (NaN if key is missing)
[ d[k].get('place', 'NaN') for k in d]
['Barcelona', 'Berlin']
[ d[k].get('year', 'NaN') for k in d]
['1987', 'NaN']
# sorted unique list of values of second level key 'place'
sorted(set([ d[k].get('place', 'NaN') for k in d]))
['Barcelona', 'Berlin']
# get all keys with same value 'Berlin' in second key 'place' (get all people born in Berlin)
[k for k in d.keys() if d[k].get('place', 'NaN') == 'Berlin']
['Mike']
# get all keys for which the second key 'year' exist
[k for k in d.keys() if d[k].get('year', False)]
['Antje']
# get all possible pairs of (first, second) keys
[ (k1,k2) for (k1, v) in d.items() for k2 in v ]
[('Antje', 'place'), ('Antje', 'year'), ('Mike', 'place')]
# exchange/replace/reorder key with value: place -> name mapping
newdict = dict((d[k].get('place', 'NaN'), k) for k in d.keys())
{'Berlin': 'Mike', 'Barcelona': 'Antje'}
read more
https://gist.github.com/hrldcpr/2012250
http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html
http://blog.amir.rachum.com/blog/2013/01/02/python-the-dictionary-playbook/