I need to iterate through a complex dictionary and modify it according to several conditions.
This is a very basic example of the dict
a = {
'x' : ["x1", "x2", 'x3'],
'y' : [
{'y1' : 1},
{'y2' : 2.0},
{'y3' : True},
{'y4' : 99},
],
'z' : {
'x' : ["a1", "a2", 'a3'],
'y' : [
{'y1' : 66},
{'y2' : False},
{'y3' : 3},
{'y4' : 4.3},
]
},
'y3' : "Delete Me"
}
ĂŽterating through it, is also no problem like:
pTypes = [str, bool, int, float]
def parse(d, c):
t = type(d)
if t == dict:
for k, v in d.items():
parse(v, c+[k])
elif t == list:
for i, p in enumerate(d):
parse(p,c+[i])
elif t in pTypes:
print(c,'=>',d)
else:
print('Error: ',c,d,t)
parse(a,[])
My problem is, that I need to delete all items which have a key == ‘y3’ or a value > 50
Additionally all strings need to be enclosed by ‘-‘ like ‘x1’ => ‘-x1-‘
Just modifing the data does not work (is not persistent)
...
elif t in pTypes:
if t == str:
d = '-'+d+'-'
...
And I have no idea how to remove items while iterating the dict itself.
Since the dict can be huge, i would prefer not to make a "reduced" copy of the original.
Can anybody help?
>Solution :
The exact expected output is unclear, but since you are iterating a nested structure, better generate a new object.
Keeping your original recursive logic, you should add a return at each step to propagate your objects:
def parse(d):
if isinstance(d, dict):
return {k: parse(v) for k, v in d.items()
if k != 'y3' and not
(isinstance(v, (int, float)) and v>50)}
elif isinstance(d, list):
return [parse(x) for x in d]
elif isinstance(d, str):
return f'-{d}-'
else:
return d
out = parse(a)
Output:
{'x': ['-x1-', '-x2-', '-x3-'],
'y': [{'y1': 1}, {'y2': 2.0}, {}, {}],
'z': {'x': ['-a1-', '-a2-', '-a3-'],
'y': [{}, {'y2': False}, {}, {'y4': 4.3}]}}