I have the following list of nested dictionaries and lists. I want to create a new parent (L0
) category called 'food'
, and shift all the values in the fruit
and vegs
dictionaries one step down (so that 'L0': 'fruit'
becomes 'L1': 'fruit'
, 'L1': 'banana'
becomes 'L2': 'banana'
, etc).
D = [{
"L0": "fruit",
"L1_list": [
{
"L1": "banana"
},
{
"L1": "apple",
"L2_list": [
{
"L2": "Green apple"
},
{
"L2": "Red apple"
}
]
},
{
"L1": "kiwi"
}
]
},
{
"L0": "vegs",
"L1_list": [
{
"L1": "potato"
},
{
"L1": "carrot"
}
]
}]
The excepted output should look like this:
Expected_output = [
{
"L0": "food",
"L1_list": [
{
"L1": "fruit",
"L2_list": [
{
"L2": "banana"
},
{
"L2": "apple",
"L3_list": [
{
"L3": "Green apple"
},
{
"L3": "Redapple"
}
]
},
{
"L2": "kiwi"
}
]
},
{
"L1": "vegs",
"L2_list": [
{
"L2": "potato"
},
{
"L2": "carrot"
}
]
}
]
}
]
Now, because my dictionaries can vary in size and how deep they can go, I need a programmatic solution. So I thought I would create a recursive function that iterates util it reaches the end of the tree. As the function reaches the end of a particular branch, it would add 1 to the key (L0
--> L1
, L1_list
--> L2_list
). Although the process does indeed shift everything one level down, I can't figure out how to rebuild the initial structure. In particular, I can't bring the children back into their respective list.
Final_list = []
def digger(list_to_dig):
import re
for x in list_to_dig:
for k,v in x.items():
if isinstance(v, list):
print("keep digging")
digger(v)
elif isinstance(x, dict):
new_D = {}
new_k = "L" + str(int(re.sub("L", "", k)) + 1)
new_D[new_k] = v
temp = re.sub("L", "", k)
new_child_list = "L" + str(int(re.sub("_list", "", temp)) + 2) + "_list"
new_D[new_child_list] = ""
Final_list.append(new_D)
else:
print("no dictionary avail")
pass
print("_________")
print(Final_list)
print("_________")
test = digger(D)
Any suggestions on how I should tackle this? Many thanks
Following the suggestion of @running.t I have tried to use the dict.pop
method. However, because it takes place within an iteration, it pops the old key, creates and inserts the new one, but on the next iteration will take the new key just created, pops it, and creates and inserts a new new key, and so on (although it doesn't go into an infinite loop either).
Here is a simplified example to illustrate the problem:
Step 1 create new top level dict
new_top_level = {"L0": "Food"}
new_dict = {}
for k, v in new_top_level.items():
lst_k = "L" + str(int(re.sub("L", "", ka)) + 1) + "_list"
new_dict[k] = v
new_dict[lst_k] = []
Step 2 add the old tree in the new list
old_d = {'L0': 'Fruit', 'L1_list': [{'L1': 'Green apple'}, {'L1': 'Red apple'}]}
new_dict[lst_k].append(old_d)
Step 3 add 1 to all the keys of the old tree
def digger(list_to_update):
import re
pattern1 = r"L.$"
pattern2 = r"L._list"
for x in list_to_update:
for k1, v1 in x.items():
if re.match(pattern1, k1):
new_k1 = "L" + str(int(re.sub("L", "", k1)) + 1)
x[new_k1] = x.pop(k1)
elif re.match(pattern2, k1):
temp = re.sub("L", "", k1)
new_k1 = "L" + str(int(re.sub("_list", "", temp)) + 1) + "_list"
x[new_k1] = x.pop(k1)
digger(v1)
test = digger(new_dict[lst_k])