Listas y tuplas.
Acceso al contenido
Aunque listas y tuplas son colecciones de datos diferentes, ya dijimos que comparten muchas características y comportamientos; entre estos últimos están su 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 anidados dentro de la lista o tupla principal?.
Un ejemplo de ello podría ser el siguiente: una lista que contiene "registros" que se comportan, a su vez como listas (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 datos de la primera sublista, deberemos expresarlo como sigue: print([mi_lista_b[0][0]) (nos devuelve -> Lucia). Observa que empleamos una pareja de corchetes para identificar el registro (en este caso el primero [0]) y a continuación una segunda pareja para identificar el datos que deseamos (en este caso también el primero [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 apartado 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 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 (->4) es 4, por lo que el anterior (elemento 2 -> 3).
Ahora bien 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 suponemos 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 da igual contenido que lista0, esto es, 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.