Colecciones de datos (1). Listas
Las listas son las colecciones de datos más simples con que cuenta Python. En esta entrada vamos a estudiarlas con cierto detalle.
Como decíamos en una entrada anterior, las colecciones de datos (arreglos o matrices) nos permiten almacenar en una única dirección de memoria RAM un conjunto de datos, mientras que con una variable únicamente podemos acceder a uno concreto. Los diferentes lenguajes de programación imponen condiciones específicas a estas colecciones, pero la ventaja de los arreglos en relación a las variables en cuanto a la cantidad de información a la que podemos acceder es evidente. Si además el lenguaje dispone de diferentes tipos de colecciones, la flexibilidad en el acceso es evidente.
Este es el caso de Python que, como dijimos en la entrada anterior, cuenta con cuatro tipos de colecciones de datos. Analicemos en primer lugar la más simple y posiblemente más flexible de ellas: Las listas.
Definíamos antes una lista como un conjunto ordenado de datos o elementos de diferentes tipos (caracteres, cadenas, enteros, reales, booleanos) que pueden estar repetidos. Estas características, junto con las operaciones permitidas sobre la lista, la convierten en un recurso muy flexible para el almacenamiento de datos, superando ampliamente en cuanto a flexibilidad a los arreglos o matrices que vimos tanto en PSeInt como en OOo Basic.
La forma de declarar una lista es en Python tan simple como el ejemplo que sigue:
vListaDiasSemana = ["lunes","martes","miércoles","jueves","viernes"]
- Observa que una lista se declara y asigna de la misma forma y con el mismo operador que una variable, unificando ambos procesos en una única sentencia (frente al procedimiento seguido en PSeInt.
- El identificador de la lista es su delimitador: los corchetes.
- Los elementos o datos se separan mediante comas.
- Aunque en esta lista todos los elementos son del mismo tipo, no es esta una restricción aplicable a los conjunto de datos en Python, como ya dijimos.
- Aunque podemos escribir la lista sin más ([]), para poder acceder a ella o a alguno de sus elementos, es necesario asignarla a una variable (vListaDiasSemana)
- Las listas pueden contener 0 elementos o todos los que deseemos.
Es importante entender que cada elemento de la lista ocupa una posición dentro de ella y que esta posición o índice es el que nos permite acceder a cada uno de los elementos contenidos en la lista de forma similar a como accedemos al contenido de una variable, aunque respetando su propia sintaxis. Si para acceder al contenido de una variable únicamente tenemos que referenciarla, para acceder a un elemento determinado de una lista, debemos hacerlo especificando su índice. Si no indicamos ese índice se supone que estamos accediendo a todo el contenido de la lista, algo que es posible en determinadas condiciones, pero no en todas. Vemos unos ejemplos:
vPalabra = "casa"
vlstPalabras = ["casa","mesa","armario"]
print(vPalabra) -> devuelve casa
print(vlstPalabras[0]) -> devuelve casa
print(vlstPalabras) -> devuelve ['casa','mesa','armario']
- Si la lista vlstPalabras estuviera vacía, print(vlstPalabras[0]) provocaría un error (no hay elemento vlstPalabras[0]), no así print(vlstPalabras) -> devuelve [].
Podemos conocer el número de elementos de una lista mediante la función len(), del cual podemos informar directamente o asignar a una variable para su posterior tratamiento. Por ejemplo, en vListaDiasSemana:
print(len(vListaDiasSemana)) -> Devuelve 5
vNumDiasSemana=len(vListaDiasSemana)
print(vNumDiasSemana) -> Devuelve 5
Una lista es modificable: podemos cambiar su contenido, añadir elementos o borrarlos, todo ello de forma muy simple:
- Para cambiar un elemento, únicamente tenemos de reasignarle nuevo contenido haciendo uso del índice (lugar que ocupa el elemento en la lista) que le corresponde. Por ejemplo, siendo la lista...
vlstPalabras = ["casa","mesa","armario"]
... si queremos cambiar vlstPalabras[0] "casa" por "cama" diremos...
vlstPalabras[0] = "cama"
- Para añadir un nuevo elemento a la lista anterior utilizaremos la siguiente expresión (el nuevo elemento se añade al final de la lista):
vlstPalabras = vlstPalabras + ["mesita"]
- Para borrar un elemento de la lista (la anterior, por seguir con el ejemplo), la instrucción es la siguiente:
del vlstPalabras[2] -> Borra el elemento "armario" que ocupa la tercera posición.
Podemos trabajar con varias listas, por ejemplo dos, y unirlas en una tercera. Supongamos dos listas:
vlstMuebles1=["mesa","silla","taburete"]
vlstMuebles2=["sofá","armario","mesita"]
... la unión de ambas mediante la instrucción...
vlstMuebles= vlstMuebles1+vlstMuebles2
... nos da como resultado...
print(vlstMuebles) -> Devuelve ['mesa', 'silla', 'taburete', 'sofá', 'armario', 'mesita']
NOTA. Esta operación es equivalente a la unión de conjuntos (A U B), salvo que en la unión e conjuntos, todos los que son elementos intersección no se repiten, pero en la unión de listas sí, ya que éstas admiten la posibilidad de que se repitan sus elemento. Esto es debido a que lo que marca la pertenencia a la lista es en realidad la posición que ocupa cada elemento y que podemos identificar mediante su índice.
Además de unir dos listas en una tercera, también podemos considerar otras opciones, ya que una lista puede estar formada por una serie de elementos/datos (lista simple), pero también por una combinación de elementos y listas o por una colección de listas. La primera formulación ya la conocemos, tanto en su presentación más sencilla, como resultado de la unión o suma de dos listas; veremos a continuación las otras dos.
- Lista resultante de la unión de una lista con otra mediante inclusión. Sea la lista inicial vlstMuebles1=["mesa","armario"] y queremos modificarla para que esté conformada por la estructura de contenidos Muebles + Muebles de asiento; para ello creamos una segunda lista con muebles de asiento (vlstAsientos=["silla","taburete","sillón","tresillo"]) y la incorporamos como elementos de la lista original:
vlstMuebles=["mesa","armario",vlstAsientos]
... obteniendo como resultado
print(vlstMuebles) -> Devuelve ['mesa', 'armario', ['silla', 'taburete', 'sillón', 'tresillo']]
Obsérvese que lo que alteramos es la estructura de la primera lista, no unimos ambas; de ahí que los elementos de la segunda lista (que ocupa como elemento de la primera la posición 3 (vlstMuebles[2]), aparecen delimitados como lista mediante []. Esto es importante entenderlo, ya que el acceso a los contenidos de esta lista anidada se rigen por su doble posicionamiento: como elementos [2] de la lista principal y como elementos [x] de la lista secundaria. Si solicitamos el contenido de la posición [2], obtenemos...
print(vlstMuebles[2]) -> Devuelve ['silla', 'taburete', 'sillón', 'tresillo']
... por lo que si lo que deseamos es obtener el contenido de la posición 2 de la lista anidada (taburete), deberemos referenciarlo indicando ambos índice: el primero como elemento de la lista principal y el segundo de la lista anidada:
print(vlstMuebles[2][1]) -> Devuelve taburete
- Un procedimiento similar se sigue para construir una lista formada por listas (lista de listas, su se prefiere). Por ejemplo, supongamos que tenemos un conjunto de listas cuyos elementos representan subconjuntos de un conjunto principal y queremos representar esa pertenencia transformado el conjunto principal en una lista de listas, cuyos elementos son esos subconjuntos.
lstFrutas=["pera","manzana","plátano"]
lstLegumbres=["garbanzo","lenteja","haba"]
lstHortalizas=["zanahoria","tomate","pimiento"]
lstVegetales=[lstFrutas,lstLegumbres,lstHortalizas]
print(lstVegetales) -> Devuelve [['pera', 'manzana', 'plátano'], ['garbanzo', 'lenteja', 'haba'], ['zanahoria', 'tomate', 'pimiento']]
El acceso a un elemento cualquiera de cualquiera de estas tres listas sigue el procedimiento explicado antes. Por ejemplo, para acceder al elemento 2 ([1]) de la lista 3 ([2]), se realiza con las siguiente instrucción:
print(lstVegetales[2][1]) -> Devuelve tomate
El uso de bucles es una estrategia muy frecuente para recorrer los elementos de una lista y permite desarrollar procesos muy interesantes en la construcción de algoritmos. Esto es debido a la posibilidad de combinar el uso de las variables contador en combinación con los índices de las listas. Veamos un ejemplo sencillo. Supongamos una lista que contiene los nombres de los alumnos, una segunda que contiene sus apellidos y una tercera que contiene las calificaciones en una prueba.
lstNombre=["Julián","Pedro","Matilde", "Ana"]
lstApellidos=["Alonso Pérez","González López","Ramírez De Luis","Ordóñez Núñez"]
lstNotas=[8,9,7,4]
for i in range(4):
print(lstNombre[i])
print(lstApellidos[i])
print(lstNotas[i])
Devuelve
Julián
Alonso Pérez
8
Pedro
González López
9
Matilde
Ramírez De Luis
7
Ana
Ordóñez Núñez
4
Pero en Python también podemos trabajar con el bucle For directamente sobre una lista, lo que simplifica enormemente la formulación de estas estructuras. Un ejemplo sobre una de las listas anteriores. Para ello es suficiente con emplear la expresión for item in NombreLista
lstNombre=["Julián","Pedro","Matilde", "Ana"]
for item in lstNombre:
print(item,end=" ") -> Devuelve Julián-Pedro-Matilde-Ana-
NOTA. Esta segunda forma de sintaxis del bucle For en Python es específica para trabajar con bucles sobre colecciones de datos. No hablé de ella en la entrada en la que se trató el tema del bucle determinista for porque aun no habíamos sabíamos tratado el tema de las colecciones de datos en Python.
Una expresión similar a la anterior es la que usaremos para saber si un datos concreto forma parte de una lista. Sobre la lista anterior (lstNombre=["Julián","Pedro","Matilde", "Ana"]), para saber si el Carlos forma parte de la lista formularemos la siguiente instrucción: "Carlos " in lstNombre. Esta expresión devuelve un booleano (en este caso False, ya que Carlos no está en lstNombre).
Podemos asociar esta búsqueda a un condicional y en función del resultado generar una bifurcación del algoritmo o, más sencillo, añadir el elemento a la lista de nombres. Para ello primero deberemos asignar el resultado de "Carlos " in lstNombre a una variable:
vBoolA = "Carlos" in lstNombre
if vBoolA==False:
lstNombre=lstNombre+["Carlos"]
print(lstNombre) -> Devuelve ['Julián', 'Pedro', 'Matilde', 'Ana', 'Carlos']
Mucho es aun lo que falta por aprender sobre las listas y su manejo, pero no se trata de agotar el tema y ya hemos aprendido lo necesario para poder incluirlas eficazmente en nuestros algoritmos. Es por ello que creo alcanzados los objetivos de esta entrada, y más aun pensando que, de algún modo, tendrá continuidad en la siguiente, en la que trabajaremos sobre las tuplas.