Python: Una función para iterar sobre listas anidadas

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.

Python – Capítulo 13: Recorriendo una lista con la sentencia FOR

Objetivo: presentar el bucle FOR al estilo de Python.

Supongamos que tenemos una lista sobre la que tenemos que realizar algún tipo de acción que implique acceder secuencialmente a cada uno de sus elementos. Sin ir más lejos, ¿cómo haríamos para imprimir, uno por uno, cada elemento que compone la lista?

Este problema es muy común y debe poder resolverse de un modo sencillo.

Considera, por ejemplo, la siguiente lista de todos los días de la semana:


semana = ['Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado', 'Domingo']

Imprimir el listado sería tan sencillo como hacer


print (semana[0])
print (semana[1])
print (semana[2])
print (semana[3])
print (semana[4])
print (semana[5])
print (semana[6])

Recuerda, tal como explicamos en el capítulo 11, que el primer índice de una lista es el 0, y no el 1; por eso hemos recorrido los siete elementos empezando en el cero y acabando en el seis.

Eso resolvería nuestro problema. Pero, ¿y si la lista tuviera 1000 elementos? ¿Escribiríamos 1000 líneas de código para acceder a la secuencia completa de la lista?

El bucle for nos permite solucionar esto de un modo elegante. Obsérvalo en acción:

semana = ['Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes',
 'Sábado', 'Domingo']

for dia in semana:
    print(dia)

---
Lunes
Martes
Miércoles
Jueves
Viernes
Sábado
Domingo

La variable dia, definida ad hoc en el propio bucle, va a tomar, uno a uno, todos los elementos de la lista semana, comenzando por ‘Lunes’ y terminando en ‘Domingo’.

Con cada uno de estos valores realizará las acciones definidas a continuación en el cuerpo del bloque (delimitado por la indentación). En el ejemplo, simplemente imprimirá su valor.

¡Cuánta elegancia! Adoro Python.

Javier Montero Gabarró


Fecha de la última revisión: 11 de noviembre de 2012


Python – Capítulo 13: Recorriendo una lista con la sentencia FOR


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.