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.