2011-12-01 22 views
17

C'è un modo semplice per iterare su un dizionario annidato, che può consistere in altri oggetti come elenchi, tuple, quindi ancora dizionari in modo che l'iterazione copra tutti gli elementi di questi altri oggetti?Iterate over nested dictionary

Ad esempio, se si digita una chiave di un oggetto del dizionario nidificato, otterrei tutto elencato nell'interprete Python.


[modifica] ecco esempio dizionario:

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

dispiace di essere illeggibile, ma ho fatto il meglio che ho potuto.

+0

Per la seconda parte della tua domanda, potresti volere [una bella stampante] (http://www.doughellmann.com/PyMOTW/pprint/). – miku

+2

Perché down-voting senza fornire un motivo per questo? È una domanda male posta? L'esempio del dizionario è cattivo? È solo una parte di un dizionario molto più ampio per il quale voglio usare graphviz in modo automatico, se possibile senza strisciare a mano – theta

+2

beh, alcune persone sono semplicemente innescate quando vedono altre persone che tentano di iterare attraverso dizionari o tabelle hash – prusswan

risposta

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

questo non funziona per me – theta

+1

@theta: funziona bene, per un'interpretazione della tua domanda. Se vuoi che passi in rassegna gli elenchi, aggiungi un 'elif isinstance ([], (list, tuple)):' e poi 'per v in d: recurse (v)'. – naught101

+1

NOTA: l'approccio ricorsivo fallisce in caso di dotti annidati di grandi dimensioni ... Segnala errore: superata la profondità massima di ricorsione. Quindi dipende dalle tue esigenze. Utilizzare iterativo in caso di problemi con dts nidificati di grandi dimensioni. – MANU

1

Iterazione su un dizionario annidato contenente elementi nidificati imprevisti.

Ecco la mia soluzione:

# 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 

penso che l'esempio precedente è molto generale, potete modellare per il vostro caso d'uso.

0

Cosa succede ad usare un generatore involucro general-purpose, come la seguente:

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

Ottengo: 'RuntimeError: superata la profondità di ricorsione superata' – theta

+1

Le stringhe sono iterabili quindi questo esploderà se ci sono delle stringhe nella lista/dizionario – UsAaR33

2

Ecco un'altra soluzione,

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

uscita:

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

Una versione generatore di La risposta di Graddy's recurse() sopra non dovrebbe esplodere sulle stringhe e ti dà anche il composto chiave (sentiero briciola biscotto?) che mostra come sei arrivato ad un certo valore:

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) 

produce in uscita (utilizzando il dizionario esempio fornito in questione):

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

In Python 3 il secondo ciclo di rendimento dovrebbe essere sostituibile con yield from. Questo generatore potrebbe essere reso più generale sostituendo il test type(d) == dict con isinstance(d, collections.Mapping), utilizzando il mapping ABC dal modulo delle raccolte.