Transform data with level column in python
Question:
I have data like this which represents hierarchical tree structure:
[
{
"level":0,
"name":"python"
},
{
"level":1,
"name":"food"
},
{
"level":2,
"name":"banana"
},
{
"level":3,
"name":"protein"
},
{
"level":2,
"name":"apple"
},
{
"level":1,
"name":"fuel"
}
]
I want to transform it into:
[
{
"level":0,
"name":"python",
"children":[
{
"level":1,
"name":"food",
"children":[
{
"level":2,
"name":"banana",
"children":[
{
"level":3,
"name":"protein",
"children":[
]
}
]
},
{
"level":2,
"name":"apple",
"children":[
]
}
]
},
{
"level":1,
"name":"fuel",
"children":[
]
}
]
}
]
I am using python and would prefer the solution in python with or without using external libraries, (even using pandas). I would love to see the solutions, thank you in advance 🙂
Answers:
Here is one way:
def create_tree(nodes):
# add parent information to each node
for i, node in enumerate(nodes):
if node['level'] == 0:
node['parent'] = None
else:
j = i - 1
while j >= 0:
if nodes[j]['level'] < node['level']:
node['parent'] = nodes[j]['name']
break
j -= 1
node_dict = {}
for node in nodes:
node_dict[node['name']] = node
for node in nodes:
parent_name = node.get('parent')
if parent_name is not None:
parent = node_dict[parent_name]
if 'children' not in parent:
parent['children'] = []
parent['children'].append(node)
for node in nodes:
if node.get('parent') is None:
return node
return None
nodes = [
{"level":0,"name":"python"},
{"level":1,"name":"food"},
{"level":2,"name":"banana"},
{"level":3,"name":"protein"},
{"level":2,"name":"apple"},
{"level":1,"name":"fuel"}
]
tree = create_tree(nodes)
print(tree)
which gives what you wanted
{'level': 0, 'name': 'python', 'parent': None, 'children': [{'level': 1, 'name': 'food', 'parent': 'python', 'children': [{'level': 2, 'name': 'banana', 'parent': 'food', 'children': [{'level': 3, 'name': 'protein', 'parent': 'banana'}]}, {'level': 2, 'name': 'apple', 'parent': 'food'}]}, {'level': 1, 'name': 'fuel', 'parent': 'python'}]}
I suppose the order of the dictionaries in your list matters, since otherwise I wouldn’t know under which parent the children are supposed to be listed. I would suggest to write a recursive function to get the last element at level n and append the children there:
import json
input_list = [
{
"level":0,
"name":"python"
},
{
"level":1,
"name":"food"
},
{
"level":2,
"name":"banana"
},
{
"level":3,
"name":"protein"
},
{
"level":2,
"name":"apple"
},
{
"level":1,
"name":"fuel"
}
]
def get_last_elt_at_lvl(rec, lvl):
if lvl == 0:
return rec[-1]
else:
for i in range(len(rec)-1,-1,-1):
if rec[i]['children']:
r = get_last_elt_at_lvl(rec[-1]['children'], lvl-1)
if r:
return r
return None
output_list = []
for d in input_list:
if d["level"] == 0:
output_list.append(d)
else:
last_elt = get_last_elt_at_lvl(output_list, d["level"]-1)
children = last_elt.setdefault('children', [])
children.append(d)
print(json.dumps(output_list, indent=4))
Output:
[
{
"level": 0,
"name": "python",
"children": [
{
"level": 1,
"name": "food",
"children": [
{
"level": 2,
"name": "banana",
"children": [
{
"level": 3,
"name": "protein"
}
]
},
{
"level": 2,
"name": "apple"
}
]
},
{
"level": 1,
"name": "fuel"
}
]
}
]
I have data like this which represents hierarchical tree structure:
[
{
"level":0,
"name":"python"
},
{
"level":1,
"name":"food"
},
{
"level":2,
"name":"banana"
},
{
"level":3,
"name":"protein"
},
{
"level":2,
"name":"apple"
},
{
"level":1,
"name":"fuel"
}
]
I want to transform it into:
[
{
"level":0,
"name":"python",
"children":[
{
"level":1,
"name":"food",
"children":[
{
"level":2,
"name":"banana",
"children":[
{
"level":3,
"name":"protein",
"children":[
]
}
]
},
{
"level":2,
"name":"apple",
"children":[
]
}
]
},
{
"level":1,
"name":"fuel",
"children":[
]
}
]
}
]
I am using python and would prefer the solution in python with or without using external libraries, (even using pandas). I would love to see the solutions, thank you in advance 🙂
Here is one way:
def create_tree(nodes):
# add parent information to each node
for i, node in enumerate(nodes):
if node['level'] == 0:
node['parent'] = None
else:
j = i - 1
while j >= 0:
if nodes[j]['level'] < node['level']:
node['parent'] = nodes[j]['name']
break
j -= 1
node_dict = {}
for node in nodes:
node_dict[node['name']] = node
for node in nodes:
parent_name = node.get('parent')
if parent_name is not None:
parent = node_dict[parent_name]
if 'children' not in parent:
parent['children'] = []
parent['children'].append(node)
for node in nodes:
if node.get('parent') is None:
return node
return None
nodes = [
{"level":0,"name":"python"},
{"level":1,"name":"food"},
{"level":2,"name":"banana"},
{"level":3,"name":"protein"},
{"level":2,"name":"apple"},
{"level":1,"name":"fuel"}
]
tree = create_tree(nodes)
print(tree)
which gives what you wanted
{'level': 0, 'name': 'python', 'parent': None, 'children': [{'level': 1, 'name': 'food', 'parent': 'python', 'children': [{'level': 2, 'name': 'banana', 'parent': 'food', 'children': [{'level': 3, 'name': 'protein', 'parent': 'banana'}]}, {'level': 2, 'name': 'apple', 'parent': 'food'}]}, {'level': 1, 'name': 'fuel', 'parent': 'python'}]}
I suppose the order of the dictionaries in your list matters, since otherwise I wouldn’t know under which parent the children are supposed to be listed. I would suggest to write a recursive function to get the last element at level n and append the children there:
import json
input_list = [
{
"level":0,
"name":"python"
},
{
"level":1,
"name":"food"
},
{
"level":2,
"name":"banana"
},
{
"level":3,
"name":"protein"
},
{
"level":2,
"name":"apple"
},
{
"level":1,
"name":"fuel"
}
]
def get_last_elt_at_lvl(rec, lvl):
if lvl == 0:
return rec[-1]
else:
for i in range(len(rec)-1,-1,-1):
if rec[i]['children']:
r = get_last_elt_at_lvl(rec[-1]['children'], lvl-1)
if r:
return r
return None
output_list = []
for d in input_list:
if d["level"] == 0:
output_list.append(d)
else:
last_elt = get_last_elt_at_lvl(output_list, d["level"]-1)
children = last_elt.setdefault('children', [])
children.append(d)
print(json.dumps(output_list, indent=4))
Output:
[
{
"level": 0,
"name": "python",
"children": [
{
"level": 1,
"name": "food",
"children": [
{
"level": 2,
"name": "banana",
"children": [
{
"level": 3,
"name": "protein"
}
]
},
{
"level": 2,
"name": "apple"
}
]
},
{
"level": 1,
"name": "fuel"
}
]
}
]