可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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)