Finding a key inside a nested dictionary with Python

Finding a key inside a nested dictionary with Python



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.





This is worth checking out : pypi.org/project/dictsearch
– Sreeram TP
Aug 24 at 19:29




3 Answers
3



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



You can define a recursive generator with try / except:


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:


isinstance


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:


set


set


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.


__next__





How does the generator work here? Don't you need to build the whole set first to check the in condition? Wouldn't it be faster to return early as in @DanielMesejo's solution? Or maybe use any(x == 'name' for x in recursive_keys(data))?
– pault
Aug 24 at 19:44



in


any(x == 'name' for x in recursive_keys(data))





@pault, Yep, I realised this a moment ago and added a recursive function which returns True when it finds a match.
– jpp
Aug 24 at 19:46


True





but what about using any with a generator (as in my edited original comment)? Won't that realize the speed up of the generator because of short-circuiting?
– pault
Aug 24 at 19:47



any





@pault, Yes, good point. I think Daniel's solution would be faster (generator expressions can be slower), but yeh that's a good solution.
– jpp
Aug 24 at 19:53



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.


dict


json.dumps



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.


"name: "






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)