2011-12-01 18 views
17

Czy istnieje łatwy sposób na iterację nad zagnieżdżonym słownikiem, który może składać się z innych obiektów, takich jak listy, krotki, a następnie ponownie słowniki, aby iteracja obejmowała wszystkie elementy tych innych obiektów?Powtórzenie zagnieżdżonego słownika

Na przykład, jeśli wpiszesz klucz zagnieżdżonego obiektu słownika, wszystkie zostaną wymienione w interpretera Pythona.


[edytuj] tutaj jest przykład słownika:

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

przepraszam za to, że nieczytelny, ale nie najlepsze, co mogłem.

+0

Do drugiej części pytania możesz potrzebować [ładnej drukarki] (http://www.doughellmann.com/PyMOTW/pprint/). – miku

+2

Dlaczego głosowanie w dół bez podania przyczyny? Czy pytanie jest źle zadawane? Czy przykład obiektu słownika jest zły? Jest to po prostu część znacznie większego słownika, dla którego chcę używać graphviz w sposób automatyczny, jeśli to możliwe, bez indeksowania ręcznie – theta

+2

cóż, niektórzy ludzie są po prostu spustoszczeni, gdy widzą innych ludzi próbujących iterować przez słowniki lub tabele mieszania – prusswan

Odpowiedz

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

to nie działa dla mnie – theta

+1

@theta: działa dobrze, dla jednej interpretacji twojego pytania. Jeśli chcesz, aby lista była również w pętli, dodaj 'elif isinstance ([], (list, tuple)):', a następnie 'for v in d: recurse (v)'. – naught101

+1

UWAGA: Rekursywne podejście kończy się niepowodzeniem w przypadku dużych zagnieżdżonych dyktatur ... Daje błąd: przekroczono maksymalną głębokość rekursji. To zależy od twoich wymagań. Użyj iteracyjnego w przypadku dużych problemów z zagnieżdżonymi dyktami. – MANU

1

Iterowanie nad zagnieżdżonym słownikiem zawierającym nieoczekiwane elementy zagnieżdżone.

Oto moje rozwiązanie:

# 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 

Myślę, że powyższy przykład jest bardzo ogólne, można je kształtować dla przypadku użycia.

0

Co za pomocą generatora otoki ogólnego przeznaczenia, jak następuje:

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

Otrzymuję: 'RuntimeError: maksymalna głębokość rekurencji została przekroczona' – theta

+1

Ciągi są iterowalne, więc to rozwinie się, jeśli masz jakieś ciągi na liście/słowniku – UsAaR33

2

Oto inne rozwiązanie,

#!/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]) 

wyjściowy:

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

wersja generatora Graddy's recurse() odpowiedź powyżej, która nie powinna eksplodować na ciągi, a także daje związek klucz (cookie szlak Okruchy?), pokazując, w jaki sposób doszedł do pewnej wartości:

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) 

produkuje wyjście (z wykorzystaniem słownika przykładzie opisanym w pytaniu):

('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'] 

W Pythonie 3 Druga pętla wydajność powinien być wymienny na yield from. Generator ten mógłby stać się bardziej ogólny poprzez zastąpienie testu type(d) == dict za pomocą isinstance(d, collections.Mapping), używając mapowania ABC z modułu kolekcji.

Powiązane problemy