Reputation: 57
I have some data like this,
menu_list = [
{'name':'ABC','parent_id':None,'id':5},
{'name':'XYZ','parent_id':5,'id':7},
{'name':'APPLE','parent_id':7,'id':8},
{'name':'Mango','parent_id':5,'id':9},
{'name':'Mango-small','parent_id':9,'id':10},
]
i was expecting the final group by result like,
ABC
----XYZ
-------- APPLE
----Mango
----Mango SMALL
The final output as a dictionary.
I have used collection module of Python, and defaultdict() method. but this do the task only for first level group. But i need the nested and outer both as well. If any suggestion that would be great help. Thanks.
Upvotes: 0
Views: 114
Reputation: 864
you can use recursive function to solve this problem.
menu_list = [
{'name':'ABC','parent_id':None,'id':5},
{'name':'XYZ','parent_id':5,'id':7},
{'name':'APPLE','parent_id':7,'id':8},
{'name':'Mango','parent_id':5,'id':9},
{'name':'Mango-small','parent_id':9,'id':10},
]
def rec_somehing(d:dict,par_id:int,depth:int)->str:
for i in d:
if i['parent_id'] == par_id:
print('....'*depth,i['name'])
rec_somehing(d,i['id'],depth+1)
rec_somehing(menu_list,None,1)
#output:
# .... ABC
# ........ XYZ
# ............ APPLE
# ........ Mango
# ............ Mango-small
If you want to get something like {'ABC': {'XYZ': 'APPLE', 'Mango': 'Mango-small'}}
you can use something like this
menu_list = [
{'name':'ABC','parent_id':None,'id':5},
{'name':'XYZ','parent_id':5,'id':7},
{'name':'APPLE','parent_id':7,'id':8},
{'name':'Mango','parent_id':5,'id':9},
{'name':'Mango-small','parent_id':9,'id':10},
]
new_dict = {}
def rec_somehing(d:dict,par_id:int,depth)->None:
if not depth:
for i in d:
if i['parent_id'] == par_id:
new_dict[i['name']] = {}
rec_somehing(d,i['id'],1)
else:
for i in d:
if i['parent_id'] == par_id:
for j in d:
if j['parent_id'] == i['id']:
if new_dict.get(list(new_dict.keys())[0]).get(i['name']) != j['name']:
new_dict[list(new_dict.keys())[0]][i['name']] = j['name']
rec_somehing(d,i['id'],1)
rec_somehing(menu_list,None,0)
print(new_dict)
#output: {'ABC': {'XYZ': 'APPLE', 'Mango': 'Mango-small'}}
if you're gonna input the same type of data -> [list with dicts of 3 items] it will be working, but if you input something else (like [list of dicts of dicts of dicts... etc]) it won't.
Upvotes: 2
Reputation: 1530
Code:
import re
ls = [
{'name':'ABC','parent_id':None,'id':5},
{'name':'XYZ','parent_id':5,'id':7},
{'name':'APPLE','parent_id':7,'id':8},
{'name':'Mango','parent_id':5,'id':9},
{'name':'Mango-small','parent_id':9,'id':10},
]
#creating new dict by id and name only
id_nm = {l['id']:l['name'] for l in ls} #Output: {5: 'ABC', 7: 'XYZ', 8: 'APPLE', 9: 'Mango', 10: 'Mango-small'}
#Another new dict by parent and child
dic = {i:[]for i in [l['parent_id']for l in ls]}
[dic[l['parent_id']].append(l['id']) for l in ls] #Output: {None: [5], 5: [7, 9], 7: [8], 9: [10]}
#Another new dict with parent with most child
nd = [{id_nm[k]:v} for k,v in dic.items() if len(v)>1][0] #Output: {'ABC': [7, 9]}
#Here loop to child list of nd, to findout the grad child/ meanwhile also replace the ids with name using above `id_nm` dict
for ls in nd.values():
for i,l in enumerate(ls):
ls[i]={id_nm[l]:id_nm[dic[l][0]]}
nd
Output:
{'ABC': [{'XYZ': 'APPLE'}, {'Mango': 'Mango-small'}]}
Upvotes: 1
Reputation: 2388
Instead of fiddling with IDs, you could just organize your data the way you want it. Example:
menu_list = [
{'name': 'ABC', 'children': [
{'name': 'XYZ', 'children': [
{'name': 'APPLE', 'children': []}
]},
{'name': 'Mango', 'children': [
{'name': 'Mango-small', 'children': []}
]}
]}
]
Upvotes: 0