2011-12-01 49 views
17

¿Hay una forma fácil de iterar sobre el diccionario anidado, que puede consistir en otros objetos como listas, tuplas y luego diccionarios para que la iteración cubra todos los elementos de estos otros objetos?Iterar sobre el diccionario anidado

Por ejemplo, si escribo una clave de un objeto de diccionario anidado, obtendría todo enumerado en el intérprete de Python.


[editar] aquí es ejemplo diccionario:

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

lo siento por ser ilegible, pero lo hice lo mejor que pude.

+0

Para la segunda parte de su pregunta, es posible que desee [una bonita impresora] (http://www.doughellmann.com/PyMOTW/pprint/). – miku

+2

¿Por qué votar negativamente sin proporcionar una razón para ello? ¿La pregunta es mal hecha? ¿El ejemplo del objeto del diccionario es malo? Es solo parte de un diccionario mucho más grande para el que quiero usar graphviz de manera automatizada si es posible sin gatear a mano – theta

+2

, algunas personas simplemente se activan cuando ven a otras personas intentando iterar a través de diccionarios o tablas hash – prusswan

Respuesta

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

esto no funciona para mí – theta

+1

@theta: funciona bien, para una interpretación de su pregunta. Si también desea recorrer listas, agregue un 'elif isinstance ([], (list, tuple)):' y luego 'for v in d: recurse (v)'. – naught101

+1

NOTA: El enfoque recurrente falla en caso de dictados anidados grandes ... Da error: se ha excedido la profundidad máxima de recursión. Entonces depende de tu requerimiento. Use iterativo uno en caso de grandes problemas de dictados anidados. – MANU

1

Iteración sobre un diccionario anidado que contiene elementos anidados inesperados.

Aquí está mi solución:

# 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 

creo que el ejemplo anterior es muy general, se puede moldear para su caso de uso.

0

¿Qué pasa con el uso de un generador de envoltura de propósito general, como la siguiente:

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

Obtengo: 'RuntimeError: se excedió la profundidad máxima de recursión' – theta

+1

Las cadenas son iterables, así que esto explotará si tiene alguna cadena dentro de la lista/diccionario – UsAaR33

2

Aquí hay otra solución,

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

Salida:

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 versión del generador de La respuesta de Graddy recurse() anterior que no debería explotar en cadenas, y también le da el compuesto clave (rastro de migas de galletas?) que muestra cómo llegó a un cierto valor:

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 una salida (utilizando el diccionario ejemplo proporcionado en la pregunta):

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

En Python 3, el segundo bucle de rendimiento debe ser reemplazable con yield from. Este generador podría hacerse más general reemplazando la prueba type(d) == dict con isinstance(d, collections.Mapping), usando la Cartografía ABC del módulo de colecciones.

Cuestiones relacionadas