I have a dictionary something like this so
acc = ["key1", "key_", "four"]
dict = {"key1": "something", "key_": "something2", "three": {"four": "remove this", "five": "dsadsdsas"}}
Need to remove all this particular key from json which is mentioned in acc variable.
{key: value for key, value in dict.items() if key not in acc}
this doesn't remove the "four" key
So what can I do here?
CodePudding user response:
The reason that it does not work like you would is that the keys in your dictionary are: key1, key_ and three. three is not in acc and the value of three is kept. That this value is a dictionary is not tested and therefore not used when you filter your dictionary.
Therefore you have to use recursion to check if the item in your dictionary is itself a dictionary. If that is the case, also filter this "dictionary inside a dictionary".
For example:
# do not use dict, this is a built-in function.
# https://docs.python.org/3/library/functions.html
d = {"key1": "something", "key_": "something2", "three": {"four": "remove this", "five": "dsadsdsas"}}
def filter_dict(d: dict, acc: list = ["key1", "key_", "four"]) -> dict:
new_d = {}
for key, value in d.items():
if key in acc:
continue
if isinstance(value, dict):
new_d[key] = filter_dict(value)
else:
new_d[key] = value
return new_d
filter_dict(d)
>>> {'three': {'five': 'dsadsdsas'}}
This example will return an empty dictionary when all keys are inside acc. How to deal with those kind of dictionaries is up to you, you can change this line to deal with empty dictionaries:
new_d[key] = filter_dict(value)
CodePudding user response:
Simple trick with json.loads and its object_pairs_hook (used on decoding phase):
import json
stop_k = ["key1", "key_", "four"]
d = {"key1": "something", "key_": "something2", "three": {"four": "remove this", "five": "dsadsdsas"}}
filtered = json.loads(json.dumps(d), object_pairs_hook=lambda pairs, stop_k=stop_k: \
dict((k,v) for k, v in pairs if k not in stop_k))
{'three': {'five': 'dsadsdsas'}}
