Search for a value in a nested dictionary python

匿名 (未验证) 提交于 2019-12-03 03:09:01

问题:

Search for a value and get the parent dictionary names (keys):

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':{...},...        },... 

In above dictionary I need to search values like: "image/svg+xml". Where, none of the values are repeated in the dictionary. How to search the "image/svg+xml"? so that it should return the parent keys in a dictionary { dict1:"part2" }.

Please note: Solutions should work unmodified for both Python 2.7 and Python 3.3.

回答1:

This is an iterative traversal of your nested dicts that additionally keeps track of all the keys leading up to a particular point. Therefore as soon as you find the correct value inside your dicts, you also already have the keys needed to get to that value.

The code below will run as-is if you put it in a .py file. The find_mime_type(...) function returns the sequence of keys that will get you from the original dictionary to the value you want. The demo() function shows how to use it.

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

Output:

Found image/svg+xml mime type here: ['dict1', 'part2', '.svg']

Confirmation lookup: image/svg+xml



回答2:

Here's a simple recursive version:

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 

Example:

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


回答3:

Here are two similar quick and dirty ways of doing this type of operation. The function find_parent_dict1 uses list comprehension but if you are uncomfortable with that then find_parent_dict2 uses the infamous nested for loops.

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) 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!