Reputation: 13581
Python 3.6+ btw
From a nested dictionary, I want to print a parent-value if a child-value matches a string. To do this, I tried this recursive call
for child in traverse_dict(value, 'ready', 'y'):
print(child)
That is, when the parent-key is found, I want to (recursively) check whether any of its child-values (and child-keys) match the respective string patterns, and if yes, print. (I would collect the values eventually)
Using the same call but outside the function works as intended (try last 2 lines of example code or see below).
for i in traverse_dict(ex, 'ready', 'y'):
print(i)
# Output is
# Y
But when I try
for i in traverse_dict(ex, 'id'):
print(i)
# Output is
# checkpoint
# A
# checkpoint
# B
But I expect
# Output is
# checkpoint
# Y <= (missing this, output of traverse_dict(ex, 'ready', 'y'))
# A
# checkpoint
# B
Any idea why it FAILS when called inside the function?
See this example
ex = [
{
'Id': 'A',
'Status': { 'Ready': 'Y' }
},
{
'Id': 'B',
'Status': { 'Ready': 'N' }
}
]
def traverse_dict(
data,
*args
):
if isinstance(data, dict):
for key, value in data.items():
# FOR SUB-GENERATOR WHERE *ARGS IS PASSED 2 ARGS
try:
if key.lower() == args[0] and value.lower() == args[1]:
yield value
else:
yield from traverse_dict(value, *args)
except:
if key.lower() == args[0]:
print('checkpoint')
for child in traverse_dict(value, 'ready', 'y'):
print(child)
yield value
else:
yield from traverse_dict(value, *args)
elif isinstance(data, list):
for item in data:
yield from traverse_dict(item, *args)
for i in traverse_dict(ex, 'id'):
print(i)
for i in traverse_dict(ex, 'ready', 'y'):
print(i)
Thanks in advance!
Upvotes: 3
Views: 36
Reputation: 5329
You have passed wrong data in for child in traverse_dict(value, 'ready', 'y'):...
line. In your case the value
contains "A" because the key.lower() == args[0]
statement is True
when the key is Id
and the value is A
or B
. You should pass the 'Status'
member of the current dict.
It means the correct line: for child in traverse_dict(data['Status'], 'ready', 'y'):
Output with this line:
>>> python3 test.py
checkpoint
Y
A
checkpoint
B
Y
Upvotes: 2