How to create nested dictionaries with duplicate keys in python

ε祈祈猫儿з 提交于 2019-12-05 21:13:50

One more example using defaultdict:

from collections import defaultdict


data = defaultdict(  # State
    lambda: defaultdict(  # City
        lambda: defaultdict(list)  # Area
    )
)


data['State']['City']['Area'].append('area 1')
data['State']['City']['Area'].append('area 2')
data['State']['City']['Area'].append('area 2')


areas = data['State']['City']['Area']
print(areas)  # ['area 1', 'area 2', 'area 2']

total = len(areas)
print(total)  # 3

How to get list of items you want, using this solution:

data['State1']['Landon']['abc Area'].append('BOB')
data['State1']['Landon']['abc Area'].append('SAM')
data['State1']['Landon']['xyz Area'].append('John')
data['State2']['New York']['hjk Area'].append('Ricky')


def items_in(d):
    res = []
    if isinstance(d, list):
        res.extend(d)
    elif isinstance(d, dict):
        for k, v in d.items():
            res.extend([k] * len(items_in(v)))
    else:
        raise ValueError('Unknown data')
    return res


print(items_in(data['State1']))  # ['Landon', 'Landon', 'Landon']
print(items_in(data['State1']['Landon']))  # ['xyz Area', 'abc Area', 'abc Area']
print(items_in(data['State1']['Landon']['abc Area']))  # ['BOB', 'SAM']
print(items_in(data['State1']['Landon']['xyz Area']))  # ['John']

print(items_in(data['State2']))  # ['New York']
print(items_in(data['State2']['New York']))  # ['hjk Area']

One simple way would be to make it a list and then just add every new key to the list:

Data['State']['City']['Area'] = []
Data['State']['City']['Area'].append( ID )

You could replace the AutoVivication class with one that auto-vivificates Dictlists instead of dicts:

class AutoVivificationDL(Dictlist):  
    """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
Data = {}


values = [
    dict(State="CA", City="San Francisco", Area="North", Id="customer1"),
    dict(State="CA", City="San Francisco", Area="Embarcadero", Id="customer1"),
    dict(State="CA", City="San Francisco", Area="North", Id="customer2"),

]

for v in values:
    #grab the existing entry.  if it doesn't exist, returns a list
    li = Data.setdefault((v["State"],v["City"],v["Area"]),[])
    li.append(v["Id"])

print "Data:%s" % (Data)

output:

Data:{('CA', 'San Francisco', 'North'): ['customer1', 'customer2'], ('CA', 'San Francisco', 'Embarcadero'): ['customer1']}

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!