Objetivo: crear una función que ilustre cómo iterar sobre listas anidadas de cualquier profundidad.
Un lector del blog me planteaba ayer una interesante cuestión al hilo del artículo dedicado a la iteración sobre una lista con la sentencia for. Se preguntaba cómo proceder en el supuesto de que se tratara de listas anidadas en las que no conocemos a priori su profundidad de anidación.
Por ejemplo, supongamos que deseamos imprimir todos los enteros existentes en la siguiente lista:
lista_anidada = [1, [2, [3, 4, [5, 6], 7]], 8, [9, 10]]
Observa que el segundo elemento, que es el que presenta mayor nivel de anidación, es en realidad otra lista, cuyo segundo elemento es a su vez otra lista de la cual el tercer elemento es otra lista también. En este ejemplo en particular nos encontramos hasta cuatro niveles de profundidad. Nuestra función deberá ser genérica, en el sentido de que no conocerá de antemano la complejidad de la lista.
Una iteración ordinaria nos devolvería el siguiente resultado:
for elemento in lista_anidada:
print(elemento)
1
[2, [3, 4, [5, 6], 7]]
8
[9, 10]
No nos sirve, pues pretendemos recuperar todos los elementos simples.
Procederemos de la siguiente forma:
Vamos a recorrer la lista de principio a fin. Si el elemento a tratar es una lista habrá que imprimir sus elementos individuales; si no lo es, imprimimos directamente su valor.
Observa con cuidado la frase «si el elemento a tratar es una lista habrá que imprimir sus elementos individuales». Es exactamente el mismo problema que al inicio, salvo que está reducido a un subconjunto más reducido: la lista anidada dentro de la lista.
Al resolver esta segunda cuestión nos aparecería nuevamente una lista anidada, esta vez del tercer nivel; el problema seguiría siendo exactamente el mismo, pero cada vez más reducido.
Escenario perfecto para una función recursiva…
Para resolver la parte que dice «si el elemento a tratar es una lista», recurriremos a una función de Python que nos permite saber si un objeto es o no de un tipo determinado: isinstance().
Obsérvala en acción:
>>> a = 5
>>> b = 'casa'
>>> c = [1, 2]
>>> isinstance(a, list)
False
>>> isinstance(b, list)
False
>>> isinstance(c, list)
True
Implementar nuestra función resulta ya una tarea casi obvia:
def imprimir(lista):
for elemento in lista:
if isinstance(elemento, list):
imprimir(elemento)
else:
print(elemento)
Fíjate en la técnica recursiva: si elemento es una lista, la función vuelve a llamarse a sí misma, pero esta vez sobre una lista anidada en el siguiente nivel de profundidad. Y así sucesivamente, ahondando todo lo necesario hasta que no quede un entero sin imprimir.
def imprimir(lista):
for elemento in lista:
if isinstance(elemento, list):
imprimir(elemento)
else:
print(elemento)
lista_anidada = [1, [2, [3, 4, [5, 6], 7]], 8, [9, 10]]
imprimir(lista_anidada)
>>>
1
2
3
4
5
6
7
8
9
10
No se salva ni el apuntador.
Javier Montero Gabarró
http://elclubdelautodidacta.es/wp/2013/02/python-una-funcion-para-iterar-sobre-listas-anidadas/
El texto de este artículo se encuentra sometido a una licencia Creative Commons del tipo CC-BY-NC-ND (reconocimiento, no comercial, sin obra derivada, 3.0 unported)
El Club del Autodidacta
Consulta el índice completo de artículos relacionados con Python.
Muchas gracias, me ha ayudado bastante; yo también soy un poco autodidacta, sigue escribiendo 😉
Eso es! Ser autodidacta implica asumir plenamente la responsabilidad de tu formación. 😉
Me alegro de haberte sido útil.
Saludos
como hago para que los imprima pero en una nueva lista!!
Qué tal Silvia:
Simplemente utiliza el método append para agregar elementos a una nuevalista, cambiando el print por:
nuevalista.append(elemento)
Saludos
Extraordinario!
Saludos, y cual sería entonces la diferencia entre isinstance() y type() ?
isinstance() integra el concepto de herencia. Verifica no sólo que un objeto es instancia directa de una clase determinada (lo que hace type), sino que comprueba si el objeto tiene por antecesor, en la jerarquía de subclases la clase que le indiques.
Saludos
Que maravilla, muchas gracias!!
Gracias me sirvio de mucho
hola! estoy tratando de resolver un ejercicio al que ya la pegué 1000 vueltas y sigue dandome error. Necesito saber como puedo usaer index para poder buscar un elemento que se encuentra en una lista anidada. Ayuda!!
Este oeluche si que sabe!!. Lo que necesitaba. Con esta función y agregando para isinstance dict o demás, me facilita el trabajo.
Muy Bien.
Gracias. Me has sacado de un problema gigante.