Reputation: 129
Off the back of a similar question I asked, how would one go about cleaning a dictionary containing a variety of datatypes: nulls, empty lists, empty dicts etc, at varying levels of nesting E.g.
{
"key":"value",
"key1": {},
"key2": [],
"key3": True,
"key4": False,
"key5": None,
"key6": [1,2,3],
"key7": {
"subkey": "subvalue"
},
"key8": {
"subdict": {
"subdictkey": "subdictvalue",
"subdictkey1": {},
"subdictkey2": [],
"subdictkey3": None
}
}
}
Becomes:
{
"key":"value",
"key3": True,
"key4": False,
"key6": [1,2,3],
"key7": {
"subkey": "subvalue"
},
"key8": {
"subdict": {
"subdictkey": "subdictvalue"
}
}
}
The solution should be good for n levels of nesting (not just 1 level). Obviously I want to avoid nested loops (particularly as n could equal 3 or 4), is the only solution flattening the structure? Is there a more elegant way of going about it?
Edit: Building on @Ch3steR answer and accounting for the issue I encountered with a list containing a null, this is the final working function:
def recur(n_dict,new_d={}):
global counter
for key,val in n_dict.items():
if val or isinstance(val,bool) or (isinstance(val,list) and any(elem is not None for elem in val)):
if (isinstance(val,list) and any(elem is None for elem in val)):
counter=counter+1
else:
new_d={**new_d,**{key:val}}
if isinstance(val,dict):
new_d[key]=recur(val)
return new_d
Upvotes: 0
Views: 69
Reputation: 20669
You can use Recursion when you are dealing with an arbitrarily nested dictionary.
Try this.
def recur(n_dict,new_d={}):
for key,val in n_dict.items():
if val or isinstance(val,bool):
new_d={**new_d,**{key:val}}
if isinstance(val,dict):
new_d[key]=recur(val)
return new_d
a={
"key":"value",
"key1": {},
"key2": [],
"key3": True,
"key4": False,
"key5": None,
"key6": [1,2,3],
"key7": {
"subkey": "subvalue"
},
"key8": {
"subdict": {
"subdictkey": "subdictvalue",
"subdictkey1": {},
"subdictkey2": [],
"subdictkey3": None
}
}
}
print(recur(a))
{'key': 'value',
'key3': True,
'key4': False,
'key6': [1, 2, 3],
'key7': {'subkey': 'subvalue'},
'key8': {'subdict': {'subdictkey': 'subdictvalue'}}}
recur(n_dict,new_d={})
uses mutable default argument.
Note:
Never mutate
new_d
in-place or you will encounter this problem.
One of the way to check if your default argument is changed is use __defaults__
>>>recur(a)
>>>recur.__defaults__
({},)
>>>recur(a)
>>>recur.__defaults__
({},)
Upvotes: 2