在嵌套字典python中搜索值

时间:2014-03-04 03:32:37

标签: python python-2.7 python-3.x

搜索值并获取父词典名称(键):

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。

4 个答案:

答案 0 :(得分:14)

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

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

答案 1 :(得分:5)

这是对嵌套dicts的迭代遍历,它还会跟踪导致特定点的所有键。因此,只要在dicts中找到正确的值,您就已经拥有了达到该值所需的密钥。

如果您将代码放在.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()

输出:

  

在这里找到image / svg + xml mime类型:['dict1','part2','。svg']

     

确认查询:image / svg + xml

答案 2 :(得分:1)

以下是两种类似的快速和脏的方法来执行此类操作。函数find_parent_dict1使用列表推导但如果你对此感到不舒服,那么find_parent_dict2使用臭名昭着的嵌套for循环。

Dictionary = {'dict1':{'part1':{'.wbxml':'1','.rl':'2'},'part2':{'.wbdl':'3','.rs':'4'}},'dict2':{'part3':{'.wbxml':'5','.rl':'6'},'part4':{'.wbdl':'1','.rs':'10'}}}

value = '3'

def find_parent_dict1(Dictionary):
    for key1 in Dictionary.keys():
        item = {key1:key2 for key2 in Dictionary[key1].keys() if value in Dictionary[key1][key2].values()}
        if len(item)>0:
            return item

find_parent_dict1(Dictionary)


def find_parent_dict2(Dictionary):
    for key1 in Dictionary.keys():
        for key2 in Dictionary[key1].keys():
            if value in Dictionary[key1][key2].values():
                print {key1:key2}

find_parent_dict2(Dictionary)

答案 3 :(得分:0)

这是一种适用于嵌套列表和字典的复杂数据结构的解决方案

composer require larabook/gateway
  
    

[[[[[['d','dict1','part2','.svg','image / svg + xml']]]]]

  

包含字典和列表的复杂示例:

def search(d,search_pattern,prev_datapoint_path=[]):
    output = []
    current_datapoint = d
    current_datapoint_path = prev_datapoint_path.copy()
    if type(current_datapoint) is dict:
        for dkey in current_datapoint:
            if search_pattern in str(dkey):
                c = current_datapoint_path.copy()
                c.append(dkey)
                output.append(c)
            c = current_datapoint_path.copy()
            c.append(dkey)
            output.append(search(current_datapoint[dkey],search_pattern,c))
    elif type(current_datapoint) is list:
        for i in range(0,len(current_datapoint)):
            if search_pattern in str(i):
                output.append(current_datapoint_path.append(i))
            c= current_datapoint_path.copy()
            c.append(i)
            output.append(search(current_datapoint[i],search_pattern,c))
    elif search_pattern in str(current_datapoint):
        c = current_datapoint_path.copy()
        c.append(current_datapoint)
        output.append(c)
    output = filter(None, output)
    return list(output)enter code here

if __name__ == "__main__":
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'}}}
print(search(d, 'image/svg+xml', ['d']))