2014-03-04 231 views
6

搜索一個值搜索一個值,並得到母公司的字典名稱(鍵):嵌套字典蟒蛇

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。

+0

請不要使用矛盾的標籤......選擇一種或另一種。 –

+0

@ aj8uppal - 這是因爲,我不想在這兩個python版本中得到答案。如果它在Python 2.7中工作,它必須在Python 3.3中工作,反之亦然。因爲我們有兩臺服務器。一個是使用python2.7,另一個是最新的。我們正在編寫一個腳本,它應該在服務器上運行。對於那個很抱歉! –

回答

4

這是對嵌套字典的迭代遍歷,它追蹤所有導致特定點的鍵。因此,只要您在字典中找到正確的值,您也已經擁有了達到該值所需的密鑰。

下面的代碼將按原樣運行,如果將其放入.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', '2部分', '.SVG']

確認查找:圖像/ SVG + xml

+0

@kobehjohn:我在等待你的進一步解釋 –

+0

@LaxmikantGurnalkar你試過了嗎?您可以將所有這些代碼放入一個.py文件並運行它。它應該給你與我列出的相同的輸出。如果這是您正在尋找的內容,那麼我會提供更多文檔。如果沒有,請告訴我有什麼不同。 – KobeJohn

+0

@ kobehjohn:我忙於完成這項任務。稍後,威爾將在一小時後開始工作。一旦測試,將接受答案。謝謝 –

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) 
+0

它不適用於任意嵌套字典。 '.keys()'調用在for循環中是多餘的。 – jfs

10

下面是一個簡單的遞歸版本:

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