Cómo usar listas de listas en Python?

En Python una lista es un contenedor que puede almacenar datos de cualquier tipo, incluso puede almacenar datos de diferentes tipos. Así, una lista puede contener strings, ints, floats, etc.

Por lo tanto, nada nos prohibe que almacenar dentro de una lista otras listas, de manera que tendríamos una lista con listas adentro. Ésto es lo que conocemos como listas de listas o listas anidadas.

Creación de listas anidadas

Para crear una lista anidada tenemos que definir una variable de tipo list y en cada una de sus posiciones guardar una lista, como en el ejemplo a continuación

mi_lista = [['a', 'b'], ['c', 'd']]

Para acceder a los valores de la lista es igual que en las listas normales pero ahora vamos a usar dos índices: uno para cada lista.

En el ejemplo anterior, al acceder a mi_lista[0] lo que vamos a hacer es obtener lo que está almacenado en la posición cero, es decir la lista ['a', 'b']. Luego, si queremos acceder a la segunda letra (que sabemos que es la posición 1) usando la notación de corchetes de Python haríamos <nombre_variable>[1]. Es decir, para acceder a la letra 'b' tenemos que hacer:

lista_cero = mi_lista[0]
letra_b = lista_cero[1]

Obviamente esto es muy ineficiente y lo podemos hacer en un paso usando dos índices de la siguiente manera:

letra_b = mi_lista[0][1]

De esta manera, podemos crear listas anidadas en Python que nos permiten almacenar datos más complejos que las listas normales.

Recorrer una lista de listas

Es muy común querer recorrer una lista de listas revisando cada uno de sus valores ya sea para modificarlos o para buscar alguno específico. Para esto, lo que tenemos que hacer es generar ciclos para cada nivel de listas que queramos recorrer.

Pensemos que tenemos la siguiente lista:

mi_lista = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]

Vamos a recorrerla completa para modificar sus valores de la siguiente manera: todos los 1 los vamos a cambiar por 0 y los 0 por 1.

Para esto, lo primero que tenemos que hacer es definir la estrategia para recorrer la lista.

Si vemos bien, lo que tenemos es una lista en la que en cada posición tiene una lista, por lo que tenemos dos niveles (cada valor pertenece a dos listas, no más ni menos). Por lo tanto con dos ciclos vamos a ser capaces de recorrer todos los valores.

En primer lugar recorramos la lista exterior (llamada mi_lista) usando un ciclo for

for i in range(len(mi_lista)):

En cada iteración lo que vamos a tener es una nueva lista (mi_lista[i]) que tenemos que recorrer por lo tanto tenemos que definir un nuevo ciclo for para recorrer esa segunda lista

for i in range(len(mi_lista)):
    for j in range(mi_lista[i]):

Con lo anterior estamos recorriendo todos los valores de la lista, de hecho basta con poner un print dentro del loop anterior para darnos cuenta que vamos a imprimir todos los valores. El código sería el siguiente:

for i in range(len(mi_lista)):
    for j in range(len(mi_lista[i])):
        print(mi_lista[i][j])

Volviendo a nuestro ejemplo, lo que queremos hacer es intercambiar los 0 con los 1, por lo tanto vamos a usar condiciones para modificar los valores:

  • Si el valor actual es 1 entonces lo cambio por 0,
  • Si el valor actual es 0 entonces lo cambio por 1.

Esto lo hacemos de la siguiente manera:

for i in range(len(mi_lista)):
    for j in range(len(mi_lista[i])):
        if mi_lista[i][j] == 0:
            mi_lista[i][j] = 1
        elif mi_lista[i][j] == 1:
            mi_lista[i][j] = 0

Resumen

Vimos que Python nos permite definir listas anidadas para trabajar con datos más complejos y que podemos recorrerlas usando ciclos para modificar sus valores.

En el ejemplo que vimos recorrimos la lista completa, pero es común también querer recorrer la lista en dsitinto orden. Por ejemplo por filas o por columnas, y no toda la lista de corrido.

21