Converting list of lists into a dictionary of dictionaries in Python

I am trying to convert a list of lists data structure to a dictionary of dictionaries.

The list is defined as follows:

l = [
['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]
]


My aim is to have the dictionary structure as follows:

#{'PP' : {'Holesovice' : {'Ear-rings' : 2000, 'Skirts' : 1000},
# 'E-shop' : {'Dresses' : 1500}},
# 'BM' : {'Holesovice' : {'Butterfly' : 1600}}
#}


This bit of code does not return desired output:

labels_d = {}
items_d = {}
shops_d = {}

for index, row in enumerate(l):
items_d[row[1]] = row[3]
shops_d[row[2]] = items_d
labels_d[row[0]] = shops_d

print(labels_d)


I found some posts that deal with converting lists to dictionaries here and here but I did not make it work the way I want. Is there any 'clean' way how to achieve the structure posted above?

Using dict.setdefault(key, {}) is a good way to approach the creation of nested dictionaries of fixed depth.

l = [
['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]
]

d = {}

for tag, item, source, qty in l:
d.setdefault(tag, {}).setdefault(source, {})[item] = qty


Output

{'BM': {'Holesovice': {'Butterfly': 1600}},
'PP': {'E-shop': {'Dresses': 1500},
'Holesovice': {'Ear-rings': 2000, 'Skirts': 1000}}}


Generalization

The above solution can be made more general by building a class of nested dictionary, dropping the requirements to have a fixed depth.

class NestedDict(dict):
def __getitem__(self, item):
if item not in self:
self[item] = NestedDict()
return super().__getitem__(item)

d = NestedDict()

for tag, item, source, qty in l:
d[tag][source][item] = qty


Also notice that the class approach is created so it only creates an object if the key does not exist while the setdefault approach created an empty dict on every access.

You can use the infinitely nested defaultdict trick:

from collections import defaultdict

def nested_dict():
return defaultdict(nested_dict)

nd = nested_dict()
for a, b, c, d in l:
nd[a][c][b] = d


You can use collections.defaultdict and iterate. In this case, you can define precisely a nested dictionary to reflect your data structure.

from collections import defaultdict

L = [['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]]

d = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))

for code, item, shop, value in L:
d[code][shop][item] = value


Result

defaultdict({'BM': defaultdict({'Holesovice': defaultdict(int, {'Butterfly': 1600})}),
'PP': defaultdict({'E-shop': defaultdict(int, {'Dresses': 1500}),
'Holesovice': defaultdict(int,
{'Ear-rings': 2000, 'Skirts': 1000})})})


def toNested1(l):
def addKeyDict(map,key):
if key not in map:
item = map[key] = {}
return item
return map[key]

zz = {}
for a0,a1,a2,a3 in l :
addKeyDict( addKeyDict( zz, a0) , a2 )[a1] = a3
return zz


Here post a pretty straightforward way to compose a new dictionary:

If the items in each row of list not in the corresponding depth of dictionary, just add/append the key-value pair to the dict.

code:

list = [
['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]
]

dicta = {}
for row in list:
if row[0] not in dicta.keys():
dicta[row[0]] = {row[2]:{row[1]:row[3]}}
continue
if row[2] not in dicta[row[0]].keys():
dicta[row[0]][row[2]] = {row[1]:row[3]}
continue
if row[1] not in dicta[row[0]][row[2]].keys():
dicta[row[0]][row[2]][row[1]] = row[3]

print(dicta)


output:

{'BM': {'Holesovice': {'Butterfly': 1600}},
'PP': {'E-shop': {'Dresses': 1500},
'Holesovice': {'Ear-rings': 2000, 'Skirts': 1000}}}

Comments

Popular posts from this blog

Meaning of `{}` for return expression

Get current scroll position of ScrollView in React Native

flutter websocket connection issue