简体   繁体   English

如何从嵌套字典中获取值?

[英]How to get a value from a nested dict?

Is there an easy, concise way to get a value from a nested dict and get None if it's not there?有没有一种简单、简洁的方法可以从嵌套的 dict 中获取一个值,如果它不存在则获取None

d1 = None
d2 = {}
d3 = {"a": {}}
d4 = {"a": {"b": 12345}}
ds = [d1, d2, d3, d4]


def nested_get(d):
    # Is there a simpler concise one-line way to do exactly this, query a nested dict value, and return None if
    # it doesn't exist?
    a_val = d.get("a") if d else None
    b_val = a_val.get("b") if a_val else None
    return b_val

if __name__ == "__main__":
    bs = [nested_get(d) for d in ds]
    print("bs={}".format(bs))

This should work:这应该有效:

def nested_get(d, *keys):
    for key in keys:
        if d is None:
            break
        d = d.get(key)
    return d

OK, using a simple custom function, I can do this, as a general concise solution:好的,使用一个简单的自定义函数,我可以做到这一点,作为一般简洁的解决方案:

d1 = None
d2 = {}
d3 = {"a": {}}
d4 = {"a": {"b": 12345}}
ds = [d1, d2, d3, d4]


def get_nested_dict_value(d, *args):
    for a in args:
        d = d.get(a) if d else None
    return d


if __name__ == "__main__":
    bs = [get_nested_dict_value(d, "a", "b") for d in ds]
    print("bs={}".format(bs))

If you want to get a little dirty, you can create a custom class that extends how a typical dictionary handles subscripting.如果您想弄点脏东西,可以创建一个自定义类来扩展典型字典处理下标的方式。

class QueryDict(dict):
    def __getitem__(self, keys):
        current = self
        try:
            for key in keys:
                current = dict.__getitem__(current, key)
            return current
        except (TypeError, KeyError):
            return None


d = {"a": {"b": {"c": 12345}}}
d = QueryDict(d)
print d['a','b','c'] # 12345
print d['a,c,e'] # None

Or, if you're trying to dynamically call entries, it might be better to allow keys to be passed in by a comma-separated string.或者,如果您尝试动态调用条目,最好允许通过逗号分隔的字符串传入键。

class QueryDict(dict):
    def __getitem__(self, key_string):
        current = self
        try:
            for key in key_string.split(','):
                current = dict.__getitem__(current, key)
            return current
        except (TypeError, KeyError):
            return None


d = {"a": {"b": {"c": 12345}}}
d = QueryDict(d)
print d['a,b,c'] # 12345.
print d['a,c,e'] # None

If you'd rather specify your "path" into the nested dict as a string path (like a directory) rather than a set of individual keys, this has worked for our needs:如果您更愿意将嵌套字典中的“路径”指定为字符串路径(如目录)而不是一组单独的键,这可以满足我们的需求:

def deep_get(d, path, default=None):
    """Get a deeply nested value in a dict based on multiple keys

    :param d: The dictionary
    :param path: The key path to search separated by '/'
    :param default: The default value to return if there is nothing
    :returns: The value at the given path or the default
    """
    dd = d
    split = path.split("/")
    for i, key in enumerate(split):
        try:
            dd = dd.get(key, {})
        except AttributeError as exc:
            p = "/".join(split[0:i])
            raise AttributeError("{} at {}".format(exc.message, p)), \
                None, sys.exc_info()[2]
    return dd or default

where the usage is as simple as用法很简单

d = {
  'a': {
    'b': {
      'c': {
        'd': "hi!"
      }
    }
  }
}

print deep_get(d, 'a/b/c/d')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM