Acceso a listas y a tuplas
Colecciones de datos
Aunque listas y tuplas son colecciones de datos diferentes, ya dijimos que comparten muchas características y comportamientos; entre estos últimos están su posible contenido y el modo en que podemos acceder a él.
El acceso a los elementos de las listas y las tuplas es un procedimiento de uso muy frecuente y de mucha utilidad práctica, por lo que interesa conocer cómo realizarlo. Ya sabemos cómo es el procedimiento básico por haberlo visto al hablar de ambas colecciones de datos (v.g. print(mi_tupla_a[0] nos devuelve en pantalla el primer elemento de la tupla), pero esto nos sirve cuando la tupla o la lista contienen elementos simples (vg mi_lista_a = [12,23,43,56]), pero, ¿ cómo accedemos a los elementos complejos, a las listas o tuplas anidadas dentro de la lista o tupla principal?.
Un ejemplo de ello podría ser el siguiente: una lista que contiene "registros" que se contienen a su vez una lista (1):
mi_lista_b = [['Lucía','Martínez Alonso','P4'],['Mario','Carcedo Suárez','P3'],['Carlota','Álvarez López','P2']]
Veamos mediante código distintas posibilidades de acceso al contenido de esta lista. Denominaré registro a cada una de las tres sublistas y dato a cada uno de los elementos de cada uno de los registros (dato -> nombre, dato -> apellidos, dato -> curso)
#Acceso a la lista completa
print(mi_lista_b)
#Captura del primer registro
reg1 = mi_lista_b[0]
#Acceso al primer registro de la lista
print(mi_lista_b[0])
#Acceso al primer registro que pasamos previamente a reg1
print(reg1)
#Acceso al primer dato (dato -> nombre) de cada uno de los registros de la lista
reg_nombres = [[mi_lista_b[0][0]], [mi_lista_b[1][0]],[mi_lista_b[2][0]]]
print(reg_nombres)
#Acceso al primer dato del nueva lista reg_nombres
print(reg_nombres[0])
#Otro modo de acceso (ahora reg_nombres_b es una lista de elementos imples
reg_nombres_b = [mi_lista_b[0][0], mi_lista_b[1][0],mi_lista_b[2][0]]
print(reg_nombres_b)
En este script estamos jugando con diferentes formas de acceder al contenidos de una lista compleja (lista de listas). Podemos diferenciar el modo de acceder al conjunto de la lista print(mi_lista_b) y a su primer elemento print(mi_lista_b[0]). En el primer caso nos devuelve todos los registros de la lista (la lista con sus sublistas...
[['Lucía', 'Martínez Alonso', 'P4'], ['Mario', 'Carcedo Suárez', 'P3'], ['Carlota', 'Álvarez López', 'P2']]
... y en el segundo sólo el primer registro (la primera sublista)
['Lucía', 'Martínez Alonso', 'P4']
Si lo que queremos es acceder al primer dato de la primera sublista, deberemos expresarlo como sigue:
[mi_lista_b[0][0]]) - nos devuelve Lucia
Observa que empleamos una pareja de corchetes para identificar el primer registro de la lista principal (que aquí ni se nombra) reg_nombres_b y que se concreta como mi_lista_b[] y a continuación una segunda pareja de corchetes para identificar el dato que deseamos (también el primero [0][0])
Haciendo extensible este procedimiento, podemos crear una lista de listas que contienen como único registro el nombre de cada alumno...
reg_nombres = [[mi_lista_b[0][0]], [mi_lista_b[1][0]],[mi_lista_b[2][0]]]
... o, como alternativa, una lista de elementos simples con el mismo contenido
reg_nombres_b = [mi_lista_b[0][0], mi_lista_b[1][0],mi_lista_b[2][0]]
La diferencia es sutil pero fundamental: en el primer caso delimitamos doblemente con corchetes cada elemento, en el segundo no. Con el primer procedimiento obtenemos una lista de listas simples (de un sólo elemento o dato cada una)...
[['Lucía'], ['Mario'], ['Carlota']]
... y con el segundo una lista simple de tres elementos (2)
['Lucía', 'Mario', 'Carlota']
Además de acceder a elementos concretos de la lista o de la tupla, también podemos hacerlo a un subconjunto de datos mediante el operador :. De este operador ya hablamos en esta entrada, pero dejamos aplazado su tratamiento para relacionarlo con los procedimientos de acceso al contenido, motivo por el que corresponde ahora tratarlo.
Este operador presenta una formulación básica de uso lista/tupla[inicio:fin] en la que se indica la posibilidad de delimitar el inicio del subconjunto y su final (mejor dicho, el elemento previo a su final). Por ejemplo, para lista0 = [1,2,3,4,5,6,7,8,9], print(lista0[0:3]) nos devuelve [1,2,3], dado que se cuentan los elementos empezando por 0 y el elemento posición 3 es 4, por lo que el anterior (elemento 2 -> 3).
Ahora podemos omitir tanto el elemento inicio como el elemento fin. En el primer caso (vg. lista0[:3]) el resultado será el mismo que antes ([1,2,3]) ya que la ausencia del delimitador inicio implica partir del primer elemento de la lista (o de la tupla). Si omitimos el elemento final (vg lista0[2:]) implícitamente se supone que deseamos ir desde el elemento inicio (posición 2 -> 3) hasta el final de la lista. En consecuencia, para lista0 -> [3,4,5,6,7,8,9].
Otra forma de acceder a segmentos del contenido de listas o tuplas es empleando índices negativos...
print(lista0[-5:-3])
#-> devuelve [5,6]
print(tupla0[-2:])
#-> Para tupla0, igual resultado que para lista0: devuelve (8,9)
... debido a que los valores negativos remiten al orden inverso en el acceso al contenido de listas y tuplas.
NOTAS
1 El mismo ejemplo podríamos plantear mediante una tupla de tuplas, una lista de tuplas o una tupla de listas.
2 Podríamos hacer exactamente lo mismo con una tupla y obtendríamos los mismos resultados