Reputation: 197
I have a nested dictionary and i want to iterated whole dictionary to check for specific key. If its matched I want to return all keys which I iterated over to reach that specific key.
My Dictionary:
d = {
"aaa":{
"bbb":"xyz",
"ccc":{
"description":"xyz",
"data":"abc"
}
"description":"xyz"
}
"xxx":{
"description":"xyz",
"bbb":{
"ccc":{
"ddd":{
"description":"xyz"
}
}
}
}
}
Excpected output:
aaa--description
aaa--ccc--description
xxx--description
xxx--bbb--ccc--ddd--description
I tried the below code but am not getting expected output
tmp_str = ""
def iter_dict(d):
global tmp_str
for key in sorted(d.keys()):
if type(d[key]) == dict and len(d[key]) > 0:
tmp_str += "--%s" %key
iter_dict(d[key])
elif key == "description":
tmp_str += "--%s\n" %(key)
for key in d.keys():
tmp_str += "\n\n%s" %key
iter_dict(d[key])
print tmp_str
Please share your ideas.. thanks
Upvotes: 0
Views: 550
Reputation: 24232
One way to do it with a recursive generator:
d = {
"aaa":{
"bbb":"xyz",
"ccc":{
"description":"xyz",
"data":"abc"
},
"description":"xyz"
},
"xxx":{
"description":"xyz",
"bbb":{
"ccc":{
"ddd":{
"description":"xyz"
}
}
}
}
}
def paths_to_key(key, d, current_path=None):
if current_path is None:
current_path = []
for k, v in d.items():
if k == key:
yield current_path + [key]
else:
if isinstance(v, dict):
path = current_path + [k]
yield from paths_to_key(key, v, path)
for path in paths_to_key('description', d):
print(path)
Output:
['xxx', 'description']
['xxx', 'bbb', 'ccc', 'ddd', 'description']
['aaa', 'ccc', 'description']
['aaa', 'description']
Upvotes: 1
Reputation: 101929
You need to keep track of the keys you have seen when recursing. Just add a parameter to your iter_dict
function and push/pop the keys there.
Also: do not use this global tmp_str
, just return the value.
def iter_dict(d, rec_keys=None):
rec_keys = rec_keys or []
results = []
for key, value in sorted(d.items(), key=lambda x: x[0]):
if isinstance(value, dict) and value:
results.append(iter_dict(value, rec_keys + [key]))
elif key == "description":
results.append('--'.join(rec_keys + ['description']))
return '\n'.join(results)
tmp_str = iter_dict(d)
This results in:
>>> print(tmp_str)
aaa--ccc--description
aaa--description
xxx--bbb--ccc--ddd--description
xxx--description
I'll leave the ordering of the lines to you as an exercise.
Upvotes: 1