【问题标题】:Is there a way to find a dictionary value using a variable length list of keys有没有办法使用可变长度的键列表来查找字典值
【发布时间】:2022-01-13 00:53:50
【问题描述】:

我有一个从 api 响应中读取的可变长度嵌套字典,我希望能够读取可以深度嵌套的键的值。

例如:

responses = {'animal': {'name': 'lassy'}}

print(responses['animal']['name'])

但是我不知道响应中字典的长度,我可能会被要求找到“foo.bar.foo.bar”的值

有没有办法设置我的代码,无论响应的长度如何,我都可以访问所需的值?

【问题讨论】:

    标签: python json api


    【解决方案1】:

    循环遍历键列表,将当前关卡的引用替换为下一个键的值。

    responses = {'animal': {'name': 'lassy'}}
    keys = ['animal', 'name']
    
    r = responses
    for key in keys:
        r = r[key]
    
    print(r)
    

    【讨论】:

      【解决方案2】:

      我猜你可以只拆分响应 <string>.split(".") 然后使用循环你可以通过t

      query = "animal.name"
      responses = {'animal': {'name': 'lassy'}}
      
      query_array = query.split('.')
      result = response;
      for key in query_array:
        if key not in result:
          print('error')
          break
        result = result[key]
      print(result)
      

      【讨论】:

        【解决方案3】:

        一个很好的方法可能是编写一个通用的类:

        from typing import Hashable
        
        
        class CompoundKeyDict(dict):
            def __getitem__(self, item):
                try:
                    __ = iter(item)
                    if isinstance(item, Hashable):
                         raise TypeError() 
                    value = None
                    for key in item:
                        value = super().__getitem__(key) if value is None else value[key]
                    return value
                except TypeError:
                    return super().__getitem__(item)
        
        
        responses = CompoundKeyDict({'animal': {'name': 'lassy'}})
        
        # this still works
        print(responses['animal'])
        # but this now also works 
        print(responses[['animal', 'name']])
        # so you can do something like this as well
        print(responses['animal.name'.split('.')])
        
        print(isinstance(responses, dict))
        

        有了该类可用,您可以使用任何dict(比如d)并使用列表、生成器或任何其他可迭代的方法访问它,方法是将其转换为CompoundKeyDictd = CompoundKeyDict(d)

        关于它如何/为什么起作用的一些评论:

        • __getitem__ 被覆盖以更改访问 dict 的标准行为,但由于不可哈希的迭代不是有效的键(因为它们是可变的),这只会影响您需要的情况。
        • __ = iter(item) 对于任何不可迭代的内容,此行将失败并显示 TypeError;对于任何可迭代但也可散列(如字符串或元组)的东西,下一行仍将引发 TypeError;所以你只剩下可迭代但不可散列的键,如列表或生成器。
        • 注意super().__getitem__(key)是必填项,这调用了dict的原__getitem__;调用 self[key] 会导致无限循环
        • 请注意,您仍然可以将元组之类的可迭代对象作为键,例如 print(responses[('animal', 'name')]) 只会抛出 KeyError,除非有一个条目以 ('animal', 'name') 作为键。

        结果:

        {'name': 'lassy'}
        lassy
        lassy
        True
        

        【讨论】:

          【解决方案4】:

          你需要递归:

          def myprint(d):
              for k, v in d.items():
                  if isinstance(v, dict):
                      myprint(v)
                  else:
                      print("{0} : {1}".format(k, v))
          

          您可以在这里找到完整的答案: Loop through all nested dictionary values?

          【讨论】:

            猜你喜欢
            • 2021-06-03
            • 1970-01-01
            • 1970-01-01
            • 2023-02-24
            • 2022-10-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-05-29
            相关资源
            最近更新 更多