2011-12-01 215 views
17

有沒有一種簡單的方法來迭代嵌套字典,它可能包含其他對象,如列表,元組,然後再次字典,以便迭代覆蓋這些其他對象的所有元素?例如,如果我鍵入嵌套字典對象的鍵,那麼我將把它全部列在Python解釋器中。迭代嵌套字典


[編輯]這裏例詞典:

{ 
'key_1': 'value_1', 
'key_2': {'key_21': [(2100, 2101), (2110, 2111)], 
     'key_22': ['l1', 'l2'], 
     'key_23': {'key_231': 'v'}, 
     'key_24': {'key_241': 502, 
      'key_242': [(5, 0), (7, 0)], 
      'key_243': {'key_2431': [0, 0], 
       'key_2432': 504, 
       'key_2433': [(11451, 0), (11452, 0)] 
       }, 
      'key_244': {'key_2441': {'key_24411': {'key_244111': 'v_24411', 
           'key_244112': [(5549, 0)] 
           }, 
          'key_24412':'v_24412' 
         }, 
       'key_2441': ['ll1', 'll2'] 
       } 
      }, 
    } 
} 

遺憾的是不可讀的,但我做了最好的,我可以。

+0

對於問題的第二部分,您可能需要[漂亮的打印機](http://www.doughellmann.com/PyMOTW/pprint/)。 – miku

+2

爲什麼在沒有提供理由的情況下進行投票?質疑問題嚴重嗎?字典對象的例子不好嗎?它只是一個更大的字典的一部分,我希望如果可能的話自動使用graphviz,而無需手動抓取 – theta

+2

,有些人只是在看到其他人嘗試遍歷字典或散列表時觸發快樂 – prusswan

回答

17
def recurse(d): 
    if type(d)==type({}): 
    for k in d: 
     recurse(d[k]) 
    else: 
    print d 
+0

這對我不起作用 – theta

+1

@theta:工作正常,對你的問題有一種解釋。如果你想讓它循環遍歷列表,添加一個'elif isinstance([],(list,tuple)):'然後'在v:recurse(v)'中。 – naught101

+1

注意:如果使用大嵌套字典,則遞歸方法失敗...出現錯誤:超出最大遞歸深度。所以這取決於你的要求。在大嵌套字典問題的情況下使用迭代。 – MANU

1

對包含意外嵌套元素的嵌套字典進行迭代。

這裏是我的解決方案:

# d is the nested dictionary 

for item in d: 
    if type(item) == list: 
     print "Item is a list" 
     for i in item: print i 
    elif type(item) == dict: 
     print "Item is a dict" 
     for i in item: print i 
    elif type(item) == tuple: 
     print "Item is a tuple" 
     for i in item: print i 
    else: 
     print "Item is not a list, neither a dict and not even a tuple" 
     print item 

我覺得上面的例子非常普遍,可以陶冶它爲您的使用情況。

0

怎麼樣使用通用包裝發生器,如下所示:

def recursive(coll): 
    """Return a generator for all atomic values in coll and its subcollections. 
    An atomic value is one that's not iterable as determined by iter.""" 
    try: 
     k = iter(coll) 
     for x in k: 
      for y in recursive(x): 
       yield y 
    except TypeError: 
     yield coll 


def test(): 
    t = [[1,2,3], 4, 5, [6, [7, 8], 9]] 
    for x in recursive(t): 
     print x 
+1

我得到:'RuntimeError:超過最大遞歸深度' – theta

+1

字符串是可迭代的,所以如果您在列表/字典中有任何字符串,就會炸燬 – UsAaR33

2

這裏是另一種解決方案,

#!/usr/bin/python 

d = {'key_1': 'value_1', 
    'key_2': {'key_21': [(2100, 2101), (2110, 2111)], 
      'key_22': ['l1', 'l2'], 
      'key_23': {'key_231': 'v'}, 
      'key_24': {'key_241': 502, 
         'key_242': [(5, 0), (7, 0)], 
         'key_243': {'key_2431': [0, 0], 
            'key_2432': 504, 
            'key_2433': [(11451, 0), (11452, 0)]}, 
         'key_244': {'key_2441': ['ll1', 'll2']}}}} 

def search_it(nested, target): 
    found = [] 
    for key, value in nested.iteritems(): 
     if key == target: 
      found.append(value) 
     elif isinstance(value, dict): 
      found.extend(search_it(value, target)) 
     elif isinstance(value, list): 
      for item in value: 
       if isinstance(item, dict): 
        found.extend(search_it(item, target)) 
     else: 
      if key == target: 
       found.append(value) 
    return found 

keys = [ 'key_242', 'key_243', 'key_242', 'key_244', 'key_1' ] 

for key in keys: 
    f = search_it(d, key) 
    print 'Key: %s, value: %s' % (key, f[0]) 

輸出:

Key: key_242, value: [(5, 0), (7, 0)] 
Key: key_243, value: {'key_2433': [(11451, 0), (11452, 0)], 'key_2432': 504, 'key_2431': 
[0, 0]} 
Key: key_242, value: [(5, 0), (7, 0)] 
Key: key_244, value: {'key_2441': ['ll1', 'll2']} 
Key: key_1, value: value_1 
3

發電機版Graddy's recurse()回答上面那個不應該爆炸的字符串,也給你化合物鍵(糕餅屑線索?)示出了如何到達一定值:

def recurse(d, keys=()): 
    if type(d) == dict: 
     for k in d: 
      for rv in recurse(d[k], keys + (k,)): 
       yield rv 
    else: 
     yield (keys, d) 

for compound_key, val in recurse(eg_dict): 
    print '{}: {}'.format(compound_key, val) 

產生輸出(使用的問題所提供的示例字典):

('key_1',): value_1 
('key_2', 'key_21'): [(2100, 2101), (2110, 2111)] 
('key_2', 'key_22'): ['l1', 'l2'] 
('key_2', 'key_23', 'key_231'): v 
('key_2', 'key_24', 'key_241'): 502 
('key_2', 'key_24', 'key_243', 'key_2433'): [(11451, 0), (11452, 0)] 
('key_2', 'key_24', 'key_243', 'key_2432'): 504 
('key_2', 'key_24', 'key_243', 'key_2431'): [0, 0] 
('key_2', 'key_24', 'key_242'): [(5, 0), (7, 0)] 
('key_2', 'key_24', 'key_244', 'key_2441'): ['ll1', 'll2'] 

在Python 3的第二屈服環應該可以用yield from替換。通過使用來自收集模塊的映射ABC,用isinstance(d, collections.Mapping)代替type(d) == dict測試,可以使該生成器更一般化。