for k, v in d.iteritems():
if type(v) is dict:
for t, c in v.iteritems():
print "{0} : {1}".format(t, c)
Estoy tratando de recorrer un diccionario e imprimir todos los pares de valores clave donde el valor no es un diccionario anidado. Si el valor es un diccionario, quiero ir a él e imprimir sus pares de valores clave ... etc. ¿Alguna ayuda?
EDITAR
¿Qué tal esto? Todavía imprime una sola cosa.
def printDict(d):
for k, v in d.iteritems():
if type(v) is dict:
printDict(v)
else:
print "{0} : {1}".format(k, v)
Caso de prueba completo
Diccionario:
{u'xml': {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'},
u'port': u'11'}}
Resultado:
xml : {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'}, u'port': u'11'}
python
dictionary
Takkun
fuente
fuente
dict
como nombre de variable. Nunca hagas esto (es por eso que falla).Respuestas:
Como dijo Niklas, necesita recursividad, es decir, desea definir una función para imprimir su dict, y si el valor es un dict, desea llamar a su función de impresión usando este nuevo dict.
Algo como :
fuente
Existen problemas potenciales si escribe su propia implementación recursiva o el equivalente iterativo con stack. Vea este ejemplo:
En el sentido normal, el diccionario anidado será una estructura de datos similar a un árbol n-nario. Pero la definición no excluye la posibilidad de un borde transversal o incluso un borde posterior (por lo tanto, ya no es un árbol). Por ejemplo, aquí key2.2 mantiene al diccionario de key1 , key2.3 puntos a todo el diccionario (borde posterior / ciclo). Cuando hay un borde posterior (ciclo), la pila / recursividad se ejecutará infinitamente.
Si imprime este diccionario con esta implementación de Scharron
Vería este error:
Lo mismo ocurre con la implementación de senderle .
Del mismo modo, obtienes un bucle infinito con esta implementación de Fred Foo :
Sin embargo, Python en realidad detecta ciclos en el diccionario anidado:
"{...}" es donde se detecta un ciclo.
Según lo solicitado por Moondra, esta es una forma de evitar ciclos (DFS):
fuente
def myprint(d): stack = d.items() visited = set() while stack: k, v = stack.pop() if isinstance(v, dict): if k not in visited: stack.extend(v.iteritems()) else: print("%s: %s" % (k, v)) visited.add(k)
list(d.items())
asd.items()
devuelve una vista, no una lista, y use env.items()
lugar dev.iteritems()
Dado que a
dict
es iterable, puede aplicar la fórmula iterable de contenedor anidado clásica a este problema con solo un par de cambios menores. Aquí hay una versión de Python 2 (consulte la 3 a continuación):Prueba:
En Python 2, podría ser posible crear una personalizada
Mapping
que califique comoMapping
pero no contengaiteritems
, en cuyo caso esto fallará. Los documentos no indican queiteritems
sea necesario para aMapping
; por otro lado, la fuente da a losMapping
tipos uniteritems
método. Entonces, para la costumbreMappings
, heredecollections.Mapping
explícitamente por si acaso.En Python 3, se deben realizar una serie de mejoras. A partir de Python 3.3, las clases base abstractas viven en
collections.abc
. También se mantienencollections
para compatibilidad con versiones anteriores, pero es mejor tener nuestras clases base abstractas juntas en un espacio de nombres. Entonces esto importaabc
decollections
. Python 3.3 también agregayield from
, que está diseñado solo para este tipo de situaciones. Esto no es azúcar sintáctico vacío; puede conducir a un código más rápido e interacciones más sensibles con las corrutinas .fuente
isinstance(item, collections.Iterable)
no hay garantía parahasattr(item, "iteritems")
. Verificarcollections.Mapping
es mejor.Iterable
haría que esta solución fuera más generalizada, olvidando que, obviamente, los iterables no necesariamente lo tieneniteritems
.yield from
sintaxis.Solución iterativa alternativa:
fuente
list
) por unadeque
o incluso una cola de prioridad.Escribí una versión ligeramente diferente que realiza un seguimiento de las teclas en el camino para llegar allí
En sus datos, se imprimirá
También es fácil modificarlo para rastrear el prefijo como una tupla de claves en lugar de una cadena si lo necesita de esa manera.
fuente
Aquí hay una forma pitónica de hacerlo. Esta función le permitirá recorrer el par clave-valor en todos los niveles. No guarda todo en la memoria, sino que recorre el dict a medida que lo recorre.
Huellas dactilares
fuente
Una solución alternativa para trabajar con listas basadas en la solución de Scharron
fuente
Solución iterativa como alternativa:
fuente
O(depth)
para la solución recursiva. Lo mismo se aplica a esta versión, si estoy pensando correctamente).iters
como una pila explícita, por lo que el consumo de memoria de Big-O es el mismo, ¿o me falta algo?Estoy usando el siguiente código para imprimir todos los valores de un diccionario anidado, teniendo en cuenta dónde el valor podría ser una lista que contenga diccionarios. Esto fue útil para mí cuando analicé un archivo JSON en un diccionario y necesité verificar rápidamente si alguno de sus valores es
None
.Salida:
fuente
Aquí hay una versión modificada de la respuesta de Fred Foo para Python 2. En la respuesta original, solo se genera el nivel más profundo de anidación. Si genera las claves como listas, puede conservar las claves para todos los niveles, aunque para hacer referencia a ellas debe hacer referencia a una lista de listas.
Esta es la función:
Para hacer referencia a las claves:
para un diccionario de tres niveles.
Necesita saber el número de niveles antes de acceder a múltiples claves y el número de niveles debe ser constante (puede ser posible agregar un poco de secuencia de comandos para verificar el número de niveles de anidación al iterar a través de valores, pero no lo he hecho aún miré esto).
fuente
Encuentro este enfoque un poco más flexible, aquí solo proporciona una función de generador que emite pares de claves y valores y se puede extender fácilmente para iterar también sobre listas.
Luego, puede escribir su propia
myprint
función y luego imprimir esos pares clave-valor.Una prueba:
Salida:
Probé esto en Python 3.6.
fuente
Estas respuestas funcionan solo para 2 niveles de subdiccionarios. Para más prueba esto:
fuente