Remove extra nesting from dictionary
I have this dictionary:
mydict = {'KEY': {'KEY': {'KEY': {'KEY': ['mylist']}}}}
Is there any pythonic way to remove the nested keys and get to the last item obtaining this:
{'KEY': ['mylist']}
Without having to manually go one by one through the items like:
def simplify_dict(d: dict) -> dict:
for k, v in d.items():
for k1, v1 in v.items():
for k2, v2 in v1.items():
for k3, v3 in v2.items():
return {k: v3}
Assuming that what you are looking for is a dictionary formed of the leaf dictionaries in a hierarchy, you could do it iteratively by progressively replacing keys that contain a dictionary with the content of that dictionary:
mydict = {'KEY':
{'KEY':
{'KEY':
{'KEY': ['mylist']}
},
'KEY2':
{'KEY3':[1,2,3]}
},
'KEY4':[7,8]
}
while dict in map(type,mydict.values()):
subKeys = [k for k in mydict if isinstance(mydict[k],dict)]
mydict.update([kv for s in subKeys for kv in mydict.pop(s).items()])
print(mydict)
{'KEY4': [7, 8], 'KEY3': [1, 2, 3], 'KEY': ['mylist']}
If you want it as a new dictionary (instead of in-place), a recursive function is probably the most elegant way to achieve it:
def leaf(D):
return { k:v for s,d in D.items()
for k,v in (leaf(d).items() if isinstance(d,dict) else [(s,d)]) }
print(leaf(mydict))
{'KEY': ['mylist'], 'KEY3': [1, 2, 3], 'KEY4': [7, 8]}
If you're ok with using libraries, a ChainMap could be used to implement the recursive function:
from collections import ChainMap
def leaf(D):
return ChainMap(*(leaf(d) if type(d)==dict else {k:d}
for k,d in D.items()))
ld = leaf(mydict)
print(*ld.items())
('KEY4', [7, 8]) ('KEY3', [1, 2, 3]) ('KEY', ['mylist'])
print(dict(ld))
{'KEY4': [7, 8], 'KEY3': [1, 2, 3], 'KEY': ['mylist']}
This is a recursive function that also does some basic checks on the input dict.
def reduce_dict(d):
for k,v in d.items():
if isinstance(v, dict) \
and len(v) == 1 \
and k in v.keys():
return reduce_dict(v)
return d
mydict = {'KEY': {'KEY': {'KEY': {'KEY': ['mylist']}}}}
print(reduce_dict(mydict))
#{'KEY': ['mylist']}