user199354 user199354 - 3 months ago 11
Python Question

List to nested dictionary

I have list of levels like

levels = [["A", "B", "C", "D"], ["A", "B"], ["A", "B", "X"]]


In response nested dictionary should appear like

{
"name": "A",
"parent": -1,
"children": [
{
"name": "B",
"parent": "A",
"children": [
{
"name": "C",
"parent": "B",
"children": [
{
"name": "D",
"parent": "C",
}
],

},
{
"name": "X",
"parent": "B"
}
],

}
]
}


I know I am missing something in recursion loop.

So far this is my code

import csv
import json

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

def master_tree(data, payload, parent = -1):
if len(data) == 1:
if data[0] not in payload['name']:
payload = {'name':data[0], "parent": parent}
else:
if data[0] in payload['name']:
for k in payload['children']:
master_tree(data[1:], k, data[0])
else:
payload = {'name': data[1], "parent": data[0], 'children':[master_tree(data[1:], payload, data[0])]}

return payload


payload = AutoVivification()
payload = master_tree(["A", "B", "X"], payload)
payload = master_tree(["A", "B", "C", "D"], payload)

print json.dumps(payload, indent=4)


Problem occurs when same structure is repeated. Like A->B->C->D is already present from 1st iteration and when A->B is passed again it should ideally skip it and in last case it should add just X node under B

Answer
import csv
import json

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

def master_tree(data, payload, parent = -1):
    if len(data) == 1:
        if data[0] not in payload['name']:
            payload = {'name':data[0], "parent": parent}
    else:
        if 'name' in payload and data[0] in payload['name']:
            get_list = []
            for k in payload['children']:
                get_list.append(k['name'])
            if data[1] in get_list:
                master_tree(data[1:], k, data[0])            
            else:
                payload['children'].append(master_tree(data[1:], {'name':data[0], "parent": parent}, data[0]))

        else:
            payload = {'name': data[0], "parent": parent, 'children':[master_tree(data[1:], payload, data[0])]}

    return payload


payload = AutoVivification()
payload = master_tree(["A", "B", "X"], payload)
payload = master_tree(["A", "B", "C", "D"], payload)
payload = master_tree(["A", "B", "Q"], payload)


print json.dumps(payload, indent=4)