【问题标题】:How to get a value from a nested dict?如何从嵌套字典中获取值?
【发布时间】:2016-02-26 22:29:13
【问题描述】:

是否有一种简单、简洁的方法可以从嵌套的字典中获取值并获取 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))

【问题讨论】:

  • 您的解决方案仅适用于 2 级嵌套字典。另外,当在不同级别找到相同的键时,您希望返回什么值?
  • 您可以将两个get 方法链接在一起。例如,只需从您的函数中返回 return d.get("a").get('b') if d else None。这就是你要找的吗?

标签: python


【解决方案1】:

这应该可行:

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

【讨论】:

  • 谢谢!我刚刚写并发布了几乎完全相同的东西。
【解决方案2】:

好的,使用一个简单的自定义函数,我可以做到这一点,作为一个通用的简洁解决方案:

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))

【讨论】:

    【解决方案3】:

    如果你想弄脏一点,你可以创建一个自定义类来扩展典型字典处理下标的方式。

    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
    

    或者,如果您尝试动态调用条目,最好允许通过逗号分隔的字符串传入键。

    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
    

    【讨论】:

      【解决方案4】:

      如果您希望将嵌套字典中的“路径”指定为字符串路径(如目录)而不是一组单独的键,这可以满足我们的需求:

      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
      

      其中的用法很简单

      d = {
        'a': {
          'b': {
            'c': {
              'd': "hi!"
            }
          }
        }
      }
      
      print deep_get(d, 'a/b/c/d')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-04
        • 2022-10-07
        • 2020-01-26
        • 2019-03-05
        • 2021-12-24
        相关资源
        最近更新 更多