I currently have a recursive function that removes ALL keys that match a pattern. Here is the background:
Example Json
{
"results": [{
"name": "john doe",
"age": "100",
"owned_cars": [{
"make": "ford",
"color": "white"
}, {
"make": "bmw",
"color": "red"
}],
"wished_cars": [{
"make": "honda"
}, {
"make": "toyota",
"style": "sleek"
}, {
"style": "fat"
}]
}]
}
Here's the function:
def remove_all_keys_matching_value(d, keys_to_remove):
if not isinstance(d, (dict, list)):
return d
if isinstance(d, list):
return [remove_all_keys_matching_value(v, keys_to_remove) for v in d]
return {k: remove_all_keys_matching_value(v, keys_to_remove) for k, v in d.items() if k not in keys_to_remove}
If I run the function with these keys to remove keys_to_remove = ('make', 'name') I'll get the following result:
{
"results": [{
"age": "100",
"owned_cars": [{
"color": "white"
}, {
"color": "red"
}],
"wished_cars": [{}, {
"style": "sleek"
}, {
"style": "fat"
}]
}]
}
I want to adjust this code to be more targeted so it doesn't remove all instances of the key but rather takes into account the root value of the key/path if that makes sense.
So for example if I were to pass in a tuple containing (('owned_cars', 'make'), 'name') it would return:
{
"results": [{
"age": "100",
"owned_cars": [{
"color": "white"
}, {
"color": "red"
}],
"wished_cars": [{
"make": "honda"
}, {
"make": "toyota",
"style": "sleek"
}, {
"style": "fat"
}]
}]
}
I know I need to keep track of the root key somehow but am unsure how to fold this in. I would appreciate any help in solving this. I always struggle when the recursion gets this complex and would love to see how someone more experienced would approach it so I can improve.
While I am interested in the solution to this problem, I'm more interested in learning how to approach a problem like this? I understand whats happening at a high level in the recursive method but struggle when I need to start stepping through it. I don't know how to make the leap to adjusting the code to identify the root path.
keys_to_removewould be:(('owned_cars', 'make'), 'name')so that the strings don't have to be split to recover actual key names.("owned_cars", "make")would it only remove"make"if the immediate parent is"owned_cars"? Or is it possible that additional levels of data could exist between?