Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python check multi-level dict key existence

Many SO posts show you how to efficiently check the existence of a key in a dictionary, e.g., Check if a given key already exists in a dictionary

How do I do this for a multi level key? For example, if d["a"]["b"] is a dict, how can I check if d["a"]["b"]["c"]["d"] exists without doing something horrendous like this:

if "a" in d and isInstance(d["a"], dict) and "b" in d["a"] and isInstance(d["a"]["b"], dict) and ...

Is there some syntax like

if "a"/"b"/"c"/"d" in d

What I am actually using this for: we have jsons, parsed into dicts using simplejson, that I need to extract values from. Some of these values are nested three and four levels deep; but sometimes the value doesn't exist at all. So I wanted something like:

val = None if not d["a"]["b"]["c"]["d"] else  d["a"]["b"]["c"]["d"] #here d["a"]["b"] may not even exist

EDIT: prefer not to crash if some subkey exists but is not a dictionary, e.g, d["a"]["b"] = 5.

like image 303
Tommy Avatar asked Nov 17 '14 18:11

Tommy


People also ask

How do you check if a key exists in a dictionary python?

Check If Key Exists Using has_key() The has_key() method is a built-in method in Python that returns true if the dict contains the given key, and returns false if it isn't.

How do you check if a key value pair exists in a dictionary python?

To check if a key-value pair exists in a dictionary, i.e., if a dictionary has/contains a pair, use the in operator and the items() method. Specify a tuple (key, value) . Use not in to check if a pair does not exist in a dictionary.

How do you know if a dictionary has multiple keys?

To check if multiple keys are in a dictionary:Wrap the keys in a set object. Use the dict. keys() method to get a view of the dictionary's keys. Check if the multiple keys are present in the view of the dictionary's keys.


3 Answers

Sadly, there isn't any builtin syntax or a common library to query dictionaries like that.

However, I believe the simplest(and I think it's efficient enough) thing you can do is:

d.get("a", {}).get("b", {}).get("c")

Edit: It's not very common, but there is: https://github.com/akesterson/dpath-python

Edit 2: Examples:

>>> d = {"a": {"b": {}}}
>>> d.get("a", {}).get("b", {}).get("c")
>>> d = {"a": {}}
>>> d.get("a", {}).get("b", {}).get("c")
>>> d = {"a": {"b": {"c": 4}}}
>>> d.get("a", {}).get("b", {}).get("c")
4
like image 128
utdemir Avatar answered Oct 07 '22 17:10

utdemir


This isn't probably a good idea and I wouldn't recommend using this in prod. However, if you're just doing it for learning purposes then the below might work for you.

def rget(dct, keys, default=None):
    """
    >>> rget({'a': 1}, ['a'])
    1
    >>> rget({'a': {'b': 2}}, ['a', 'b'])
    2
    """
    key = keys.pop(0)
    try:
        elem = dct[key]
    except KeyError:
        return default
    except TypeError:
        # you gotta handle non dict types here
        # beware of sequences when your keys are integers
    if not keys:
        return elem
    return rget(elem, keys, default)
like image 36
Meitham Avatar answered Oct 07 '22 19:10

Meitham


UPDATE: I ended up writing my own open-source, pippable library that allows one to do this: https://pypi.python.org/pypi/dictsearch

like image 45
Tommy Avatar answered Oct 07 '22 19:10

Tommy