Reputation: 785
I have a data structure. It looks as follows:
data = [[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2A', 'name': 'child', 'steps': 1},
{'id': '3A', 'name': 'grandChild-A', 'steps': 2}],
[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2A', 'name': 'child', 'steps': 1},
{'id': '3B', 'name': 'grandChild-B', 'steps': 2}],
[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2B', 'name': 'child', 'steps': 1},
{'id': '3A', 'name': 'grandChild-C', 'steps': 2}],
[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2B', 'name': 'child', 'steps': 1},
{'id': '3B', 'name': 'grandChild-D', 'steps': 2}],
[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2B', 'name': 'child', 'steps': 1},
{'id': '3C', 'name': 'grandChild-E', 'steps': 2},
{'id': '4A', 'name': 'final', 'steps': 3}
],
[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2', 'name': 'child', 'steps': 1},
]
]
How my expected output is
output = {
"1" : {
"2A": {
"3A": "grandChild-A",
"3B": "grandChild-B"
},
"2B": {
"3A": "grandChild-C",
"3B": "grandChild-D",
"3C": {
"4A": "final"
}
},
"2":"child"
}
}
How can I do that? I wanted to use the enumerator, But I always everything inside 1. Thanks in advance
Update:
I have tried the following code:
parent = data[0][0]["id"]
dict_new = {}
dict_new[parent] = {}
for e in data:
for idx, item in enumerate(e):
display(item)
if idx>0:
dict_new[parent][e[idx]["id"]] = e[idx]["name"]
Upvotes: 1
Views: 83
Reputation: 8180
You can try:
d = {}
root = d
for L in data:
d = root
for M in L[:-1]:
d = d.setdefault(M["id"], {})
d[L[-1]["id"]] = L[-1]['name']
The idea is to follow each list to build a tree (thus d.setdefault(M["id"], {})
. The leaf is handled differently, because it has to be the value of 'name'.
from pprint import pprint
pprint(root)
Output:
{'1': {'2': 'child',
'2A': {'3A': 'grandChild-A', '3B': 'grandChild-B'},
'2B': {'3A': 'grandChild-C',
'3B': 'grandChild-D',
'3C': {'4A': 'final'}}}}
The solution above won't work for the following input:
data = [[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2B', 'name': 'child', 'steps': 1}]],
[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2B', 'name': 'child', 'steps': 1},
{'id': '3A', 'name': 'grandChild-C', 'steps': 2}]]
Iterating over the second list will try to add a new element 3A -> grandChild-C
to the d['1']['2B']
dict. But d['1']['2B']
is not a dict but the 'child'
string here, because of the first list.
When we iterate over the elements, we check if the key is already mapped and otherwise create a new dict (that's the setdefault
job). We can also check if the key was mapped to a str
, and if that's the case, replace the string by a fresh new dict:
...
for M in L[:-1]:
if M["id"] not in d or isinstance(d[M["id"]], str):
d[M["id"]] = {}
d = d[M["id"]]
...
Output:
{'1': {'2B': {'3A': 'grandChild-C'}}}
Upvotes: 2
Reputation: 39404
I fixed your data: (missing comma)
data = [[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2A', 'name': 'child', 'steps': 1},
{'id': '3A', 'name': 'grandChild-A', 'steps': 2}],
[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2A', 'name': 'child', 'steps': 1},
{'id': '3B', 'name': 'grandChild-B', 'steps': 2}],
[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2B', 'name': 'child', 'steps': 1},
{'id': '3A', 'name': 'grandChild-C', 'steps': 2}],
[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2B', 'name': 'child', 'steps': 1},
{'id': '3B', 'name': 'grandChild-D', 'steps': 2}],
[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2B', 'name': 'child', 'steps': 1},
{'id': '3C', 'name': 'grandChild-E', 'steps': 2},
{'id': '4A', 'name': 'final', 'steps': 3}
],
[{'id': '1', 'name': 'parent', 'steps': 0},
{'id': '2', 'name': 'child', 'steps': 1},
]
]
And I came up with this code:
output = {}
#print(data)
for lis in data:
o = output
ln = len(lis) - 1
for idx,d in enumerate(lis):
id = d['id']
if idx == ln:
o[id] = d['name']
else:
if id not in o:
o[id] = {}
o = o[id]
print('Result:')
print(output)
Upvotes: 1