I want to create data structure with nested dictionaries and duplicate keys. A detailed example is:
data['State1']['Landon']['abc Area'] = 'BOB'
data['State1']['Landon']['abc Area'] = 'SAM'
data['State1']['Landon']['xyz Area'] = 'John'
data['State2']['New York']['hjk Area'] = 'Ricky'
for z in data['State1'].keys() ,
# I should get list ['Landon', 'Landon', 'Landon']
for y in data['State1']['Landon'].keys() ,
# I should get list ['abc Area', 'abc Area', 'xyz Area']
Currently to store the data I have used extra counter key
data = Autovivification()
data[state][city][area][counter] = ID
But while parsing total entries (duplicates as well) of City/Area, I have to use nested loops till counter key.
for city in data['State1'].keys():
for area in data['State1'][city].keys():
for counter in data['State1'][city][area].keys():
for temp in data['State1'][city][area][counter].values():
cityList.append(city)
areaList.append(area)
For nested dictionaries, I found the following code posted by nosklo
class AutoVivification(dict):
"""Implementation of perl's autovivification feature."""
def __getitem__(self, item):
try:
return dict.__getitem__(self, item)
except KeyError:
value = self[item] = type(self)()
return value
and for dictionary with duplicate keys, I found code posted by Scorpil
class Dictlist(dict):
def __setitem__(self, key, value):
try:
self[key]
except KeyError:
super(Dictlist, self).__setitem__(key, [])
self[key].append(value)
how to merge Autovivification and Duplicate class code? or is there any other pythonic way to handle such scenario?
One simple way would be to make it a list and then just add every new key to the list:
You could replace the
AutoVivication
class with one that auto-vivificatesDictlists
instead ofdicts
:One more example using defaultdict:
How to get list of items you want, using this solution:
output:
You're not limited to a very simple Id value, you can add pretty much anything you want to the list. If you expect to be doing this at a number of spots,look into https://docs.python.org/2/library/collections.html#collections.defaultdict, which kinda does a built-in setdefault.
In fact, you could add IDs to a dictionary instead of a list, it's all the same.