2014-10-16 86 views
2

我在Python中有一個字典對象。我們稱之爲dict。該對象可以包含另一個字典,該字典又可以包含另一個字典等。如何從Python中的任意長度的嵌套字典中獲取密鑰

 dict = { 'k': v, 'k1': v1, 'dict2':{'k3': v3, 'k4':v4} , 'dict3':{'k5':v5, dict4:{'k6':v6}}} 

這只是一個例子。最外面的字典的長度可以是任何東西。我想通過以下兩種方式從這樣的字典對象中提取密鑰:

  1. 獲取唯一密鑰的列表。按鍵

    [k,k1,k2,k3,k4,k5,k6] 
    
  2. 獲取列表及其母公司關聯的字典所以是這樣的:

    outer_dict_keys = [k ,dict2, dict3] 
    dict2_keys = [k3,k4] 
    dict3_keys = [k5, dict4] 
    dict4_keys = [k6] 
    

最外面的字典dict長度總是在變化,所以我不能硬編碼任何東西。

達到上述結果的最佳方法是什麼?

回答

3

使用迭代和尾遞歸的混合。在引用未定義的名稱,使間距一致並從第一個結果中除去'k2'之後,我提出了下面的代碼。 (寫入和測試3.4,它應該在任何3.x上運行,並可能在2.7上運行)。需要記住的一個關鍵是,dicts的迭代順序基本上是隨機的,並隨每次運行而變化。遞歸在這裏做的深度優先訪問子字典,而不是廣度優先。對於dict0,兩者是相同的,但是如果dict4嵌套在dict2而不是dict3中,它們不會。

dict0 = {'k0': 0, 'k1': 1, 'dict2':{'k3': 3, 'k4': 4}, 
     'dict3':{'k5': 5, 'dict4':{'k6': 6}}} 

def keys(dic, klist=[]): 
    subdics = [] 
    for key in sorted(dic): 
     val = dic[key] 
     if isinstance(val, dict): 
      subdics.append(val) 
     else: 
      klist.append(key) 
    for subdict in subdics: 
     keys(subdict, klist) 
    return klist 

result = keys(dict0) 
print(result, '\n', result == ['k0','k1','k3','k4','k5','k6']) 

def keylines(dic, name='outer_dict', lines=[]): 
    vals = [] 
    subdics = [] 
    for key in sorted(dic): 
     val = dic[key] 
     if isinstance(val, dict): 
      subdics.append((key,val)) 
     else: 
      vals.append(key) 
    vals.extend(pair[0] for pair in subdics) 
    lines.append('{}_keys = {}'.format(name, vals)) 
    for subdict in subdics: 
     keylines(subdict[1], subdict[0], lines) 
    return lines 

result = keylines(dict0) 
for line in result: 
    print(line,) 
print() 
expect = [ 
     "outer_dict_keys = ['k0', 'k1', 'dict2', 'dict3']", 
     "dict2_keys = ['k3', 'k4']", 
     "dict3_keys = ['k5', 'dict4']", 
     "dict4_keys = ['k6']"] 
for actual, want in zip(result, expect): 
    if actual != want: 
     print(want) 
     for i, (c1, c2) in enumerate(zip(actual, want)): 
      if c1 != c2: 
       print(i, c1, c2) 
+0

這太棒了。謝謝Terry! – GoldenPlatinum 2014-10-17 02:25:54

相關問題