python check multi-level dict key existence
UPDATE: I ended up writing my own open-source, pippable library that allows one to do this: https://pypi.python.org/pypi/dictsearch
python check existence of multiple multi level dict keys
This looks like the perfect situation for a recursive function.
The following function takes as arguments a dictionary (event
), an ordered list of keys
and a counter variable n
incremented at each recursion.
The function looks for the n
-th element of keys
in the event
dictionary; if it finds the key, the respective value is assigned to the event
variable, the counter is incremented and the function is called recursively with the new parameters.
If the key is not found, or the n
-th element is out of keys
' range, or if event
is not a dict type anymore, the program stops and prints out the event
variable itself, which is indeed the value of the key used in the previous recursion.
Also if the very first key is not found in the dictionary, an error is shown.
def find_key(event, keys, n=0):
try:
event = event[keys[n]]
n += 1
find_key(event, keys, n=n)
except:
print(event if n != 0 else "The first key you provided was not found in the dictionary.")
As you can see, the code's logic is pretty simple and straightforward, so for instance:
event = {"key1":{"key2":{"key3":{"key4": "Hello World!"}}}}
keys = ["key1", "key2", "key3", "key4"]
find_key(event, keys)
would print out:
>>>Hello World!
Elegant way to check if a nested key exists in a dict?
To be brief, with Python you must trust it is easier to ask for forgiveness than permission
try:
x = s['mainsnak']['datavalue']['value']['numeric-id']
except KeyError:
pass
The answer
Here is how I deal with nested dict keys:
def keys_exists(element, *keys):
'''
Check if *keys (nested) exists in `element` (dict).
'''
if not isinstance(element, dict):
raise AttributeError('keys_exists() expects dict as first argument.')
if len(keys) == 0:
raise AttributeError('keys_exists() expects at least two arguments, one given.')
_element = element
for key in keys:
try:
_element = _element[key]
except KeyError:
return False
return True
Example:
data = {
"spam": {
"egg": {
"bacon": "Well..",
"sausages": "Spam egg sausages and spam",
"spam": "does not have much spam in it"
}
}
}
print 'spam (exists): {}'.format(keys_exists(data, "spam"))
print 'spam > bacon (do not exists): {}'.format(keys_exists(data, "spam", "bacon"))
print 'spam > egg (exists): {}'.format(keys_exists(data, "spam", "egg"))
print 'spam > egg > bacon (exists): {}'.format(keys_exists(data, "spam", "egg", "bacon"))
Output:
spam (exists): True
spam > bacon (do not exists): False
spam > egg (exists): True
spam > egg > bacon (exists): True
It loop in given element
testing each key in given order.
I prefere this to all variable.get('key', {})
methods I found because it follows EAFP.
Function except to be called like: keys_exists(dict_element_to_test, 'key_level_0', 'key_level_1', 'key_level_n', ..)
. At least two arguments are required, the element and one key, but you can add how many keys you want.
If you need to use kind of map, you can do something like:
expected_keys = ['spam', 'egg', 'bacon']
keys_exists(data, *expected_keys)
Python : check if the nested dictionary exist
Here's the explicit short code with try/except
:
try:
dict1['layer1']['layer2'][0]['layer3']
except KeyError:
present = False
else:
present = True
if present:
...
To get the element:
try:
obj = dict1['layer1']['layer2'][0]['layer3']
except KeyError:
obj = None # or whatever
Check key existence in nested dictionaries
If you are working with JSON, you can write a simple class to use with the dict as it is imported.
Given the following bit of JSON:
>>> js='{"a": {"b": {"c": {"d": "e"}}}}'
It would usually be decoded into a Python dict if it is comprised of object pairs:
>>> import json
>>> json.loads(js)
{u'a': {u'b': {u'c': {u'd': u'e'}}}}
As a normal Python dict, it is subject to KeyError
with missing keys. You can use the __missing__
hook to override KeyErrors
and achieve your original structure:
class Mdict(dict):
def __missing__(self, key):
return False
Now test that:
>>> md=Mdict({'a':Mdict({'b':Mdict({'c':Mdict({'d':'e'})})})})
>>> if md['a']['b']['d']:
... print md['a']['b']['d']
... elif md['a']['b']['c']:
... print 'elif', md['a']['b']['c']
...
elif {'d': 'e'}
Each level of the dict needs to be an Mdict
vs a normal Python dict
. If you are working with JSON, however, this is really easy to achieve. Just apply object_pairs_hook as you decode the JSON:
>>> js
'{"a": {"b": {"c": {"d": "e"}}}}'
>>> md=json.loads(js, object_pairs_hook=Mdict)
And that applies the class Mdict
instead the default Python dict
as the JSON is decoded.
>>> md
{u'a': {u'b': {u'c': {u'd': u'e'}}}}
>>> md['a']
{u'b': {u'c': {u'd': u'e'}}}
>>> md['a']['c']
False
The rest of the example here remains the same.
Check if at least one key of dict is contained in another dict
Use set intersections:
needed_keys = {key1, key2}
for d in data:
if needed_keys.intersection(d):
valid_data.append(d)
The intersection is only empty if no keys are shared between the needed_keys
set and the dictionary.
Note that your any(...)
function would work too, just not as efficiently as the set intersection option; perhaps you didn't realise that the any()
function actually exists?
Reaching into a nested dictionary several levels deep (that might not exist)
You can use a recursive function:
def get_value(mydict, keys):
if not keys:
return mydict
if keys[0] not in mydict:
return 0
return get_value(mydict[keys[0]], keys[1:])
If keys can not only be missing, but be other, non-dict types, you can handle this like so:
def get_value(mydict, keys):
if not keys:
return mydict
key = keys[0]
try:
newdict = mydict[key]
except (TypeError, KeyError):
return 0
return get_value(newdict, keys[1:])
Related Topics
Python: How to Keep Repeating a Program Until a Specific Input Is Obtained
How to Solve and Equation With Inputs in Python
Python | Count Number of False Statements in 3 Rows
Iterating Over Every Two Elements in a List
Convert Image Files to a CSV File
Read Multiple Images on a Folder in Opencv (Python)
Suppress Stdout/Stderr Print from Python Functions
How to Change Dd-Mm-Yyyy Date Format to Yyyy-Dd-Mm in Pandas
How to Send Keys to a Game I Am Playing,Using Python
Concatenate Two Columns in Csv: Python
Strip White Spaces from CSV File
Converting Json into Newline Delimited Json in Python
How to Convert Float into Hours Minutes Seconds
Counting the Number of Duplicates in a List
Truth Value of a Series Is Ambiguous. Use A.Empty, A.Bool(), A.Item(), A.Any() or A.All()
In Python, How to Check If a Date Is Valid
Getting the Id of the Last Record Inserted for Postgresql Serial Key With Python