Reputation: 5941
Ditionary:
data = {
"president": {
"name": "Zaphod Beeblebrox",
"species": "Betelgeusian"
}
}
What I'd like to do is return if a key named "name" exists.
if 'president' in data and 'name' in data['president']:
print("found")
This works fine but only if I have pre knowledge of the dictionary's structure. Is there a way of knowing if there's a subkey called "name" recursively? I only found how to do this for the top level.
Upvotes: 1
Views: 98
Reputation: 43494
A bit of a hacky non-traditional way would be to convert your dict
to a string using json.dumps
. Then you can search for the key as in the string.
For example:
import json
def find_key(d, key):
if not isinstance(d, dict):
return False
else:
return '"'+key+'": ' in json.dumps(d)
print(find_key(data, 'name'))
#True
One limitation is that this won't work if you can have "name: "
inside one of your values.
Upvotes: 0
Reputation: 164623
You can define a recursive generator with try
/ except
:
def recursive_keys(d):
for k, v in d.items():
try:
yield from recursive_keys(v)
except AttributeError:
yield k
'name' in set(recursive_keys(data)) # True
If you prefer, you can use isinstance
instead:
def recursive_keys(d):
for k, v in d.items():
if isinstance(v, dict):
yield from recursive_keys(v)
else:
yield k
This is relatively expensive, since you are first creating a set
of all keys before checking if an item exists in the set
. As per @pault's comment, you can use:
any(x == 'name' for x in recursive_keys(data))
For a lazy solution without generators, see @DanielMesejo's solution. This may be more efficient since it avoids expensive __next__
calls.
Upvotes: 1
Reputation: 61910
You can do a recursive search:
data = {
"president": {
"name": "Zaphod Beeblebrox",
"species": "Betelgeusian"
}
}
def r_find(target, key):
if key in target:
return True
else:
for k, v in target.items():
if isinstance(v, dict):
if r_find(v, key):
return True
return False
print(r_find(data, "name"))
print(r_find(data, "species"))
print(r_find(data, "no-name"))
Output
True
True
False
Upvotes: 2