在嵌套字典 python 中搜索值

新手上路,请多包涵

搜索一个值并获取父字典名称(键):

 Dictionary = {dict1:{
        'part1': {
            '.wbxml': 'application/vnd.wap.wbxml',
            '.rl': 'application/resource-lists+xml',
        },
        'part2':
            {'.wsdl': 'application/wsdl+xml',
            '.rs': 'application/rls-services+xml',
            '.xop': 'application/xop+xml',
            '.svg': 'image/svg+xml',
            },
        'part3':{...}, ...

   dict2:{
          'part1': {    '.dotx': 'application/vnd.openxmlformats-..'
            '.zaz': 'application/vnd.zzazz.deck+xml',
            '.xer': 'application/patch-ops-error+xml',}
          },
          'part2':{...},
          'part3':{...},...

    },...

在上面的字典中,我需要搜索如下值: "image/svg+xml" 。其中,字典中没有重复的值。如何搜索 "image/svg+xml" ?这样它应该返回字典中的父键 { dict1:"part2" }

请注意对于 Python 2.7 和 Python 3.3,解决方案应该可以不加 修改 地工作。

原文由 Laxmikant Ratnaparkhi 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 788
2 个回答

这是嵌套字典的迭代遍历,它还跟踪通向特定点的所有键。因此,一旦您在字典中找到正确的值,您也已经拥有了获取该值所需的键。

如果将下面的代码放在 .py 文件中,它将按原样运行。 find_mime_type(...) 函数返回键的序列,这些键将使您从原始字典获得所需的值。 demo() 函数展示了如何使用它。

 d = {'dict1':
         {'part1':
              {'.wbxml': 'application/vnd.wap.wbxml',
               '.rl': 'application/resource-lists+xml'},
          'part2':
              {'.wsdl': 'application/wsdl+xml',
               '.rs': 'application/rls-services+xml',
               '.xop': 'application/xop+xml',
               '.svg': 'image/svg+xml'}},
     'dict2':
         {'part1':
              {'.dotx': 'application/vnd.openxmlformats-..',
               '.zaz': 'application/vnd.zzazz.deck+xml',
               '.xer': 'application/patch-ops-error+xml'}}}

def demo():
    mime_type = 'image/svg+xml'
    try:
        key_chain = find_mime_type(d, mime_type)
    except KeyError:
        print ('Could not find this mime type: {0}'.format(mime_type))
        exit()
    print ('Found {0} mime type here: {1}'.format(mime_type, key_chain))
    nested = d
    for key in key_chain:
        nested = nested[key]
    print ('Confirmation lookup: {0}'.format(nested))

def find_mime_type(d, mime_type):
    reverse_linked_q = list()
    reverse_linked_q.append((list(), d))
    while reverse_linked_q:
        this_key_chain, this_v = reverse_linked_q.pop()
        # finish search if found the mime type
        if this_v == mime_type:
            return this_key_chain
        # not found. keep searching
        # queue dicts for checking / ignore anything that's not a dict
        try:
            items = this_v.items()
        except AttributeError:
            continue  # this was not a nested dict. ignore it
        for k, v in items:
            reverse_linked_q.append((this_key_chain + [k], v))
    # if we haven't returned by this point, we've exhausted all the contents
    raise KeyError

if __name__ == '__main__':
    demo()

输出:

在此处找到图像/svg+xml mime 类型:[‘dict1’, ‘part2’, ‘.svg’]

确认查找:image/svg+xml

原文由 KobeJohn 发布,翻译遵循 CC BY-SA 4.0 许可协议

这是一个简单的递归版本:

 def getpath(nested_dict, value, prepath=()):
    for k, v in nested_dict.items():
        path = prepath + (k,)
        if v == value: # found value
            return path
        elif hasattr(v, 'items'): # v is a dict
            p = getpath(v, value, path) # recursive call
            if p is not None:
                return p

例子:

 print(getpath(dictionary, 'image/svg+xml'))
# -> ('dict1', 'part2', '.svg')

产生多条路径(仅限 Python 3 的解决方案):

 def find_paths(nested_dict, value, prepath=()):
    for k, v in nested_dict.items():
        path = prepath + (k,)
        if v == value: # found value
            yield path
        elif hasattr(v, 'items'): # v is a dict
            yield from find_paths(v, value, path)

print(*find_paths(dictionary, 'image/svg+xml'))

原文由 jfs 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题