That's now been some days I'm looking for a solution to my problem. I won't cover all the things I tried so far and will just explain my problem.
Here are my two inputs:
unused_field_list = ['a.b', 'b.d.y', 'c.g', 'z']
my_dictionnary =
{
"a": {
"b": {
"key": "value"
},
"c": {
"f": {
"key": "value"
}
}
},
"b": {
"d": {
"y": {
"key": "value"
}
},
"g": {
"key": "value"
}
},
"c": {
"g" : {
"key": "value"
}
},
"z": {
"key": "value"
}
}
Here is the output I would like:
{
"a": {
"c": {
"f": {
"key": "value"
}
}
},
"b": {
"g": {
"key": "value"
}
}
}
So what I try to achieve is removing the "keys" I do have in my unused_field_list
from my dictionary. It's not mandatory but another good thing would be to also totally remove a key if it does not contain lower level keys (like it is the case for b.d
and c
keys in my example. Depth of the dict is not known in advance and varies.
I think this is not doable with a straightforward approach but I really hope there is a way of doing it quite simply.
CodePudding user response:
You can use recursion:
paths = ['a.b', 'b.d.y', 'c.g', 'z']
d = {'a': {'b': {'key': None}, 'c': {'f': {'key': None}}}, 'b': {'d': {'y': {'key': 'value'}}, 'g': {'key': 'value'}}, 'c': {'g': {'key': 'value'}}, 'z': {'key': 'value'}}
def rm_d(d, p = []):
if not isinstance(d, dict):
return d
r = {a:rm_d(b, p [a]) for a, b in d.items() if '.'.join(p [a]) not in paths}
return {a:b for a, b in r.items() if not isinstance(b, dict) or b}
print(rm_d(d))
Output:
{'a': {'c': {'f': {'key': None}}}, 'b': {'g': {'key': 'value'}}}
CodePudding user response:
unused_field_list = ['a.b', 'b.d.y', 'c.g', 'z']
my_dictionnary = {
"a": {
"b": {
"key": "value"
},
"c": {
"f": {
"key": "value"
}
}
},
"b": {
"d": {
"y": {
"key": "value"
}
},
"g": {
"key": "value"
}
},
"c": {
"g" : {
"key": "value"
}
},
"z": {
"key": "value"
}
}
def filter_dict(node, filter=None, path=None):
if type(node) != dict:
return node
res = {}
if filter is None:
filter = []
if path is None:
path = ""
for k, v in node.items():
subpath = f"{path}.{k}" if path != "" else k
if subpath not in filter:
subnode = filter_dict(v, filter, subpath)
if subnode != {}:
res [k] = subnode
return res
res = filter_dict(my_dictionnary, unused_field_list)
print(res)