AnteriorPosterior

08 - Contacto con los arrays o matrices (y las listas)

Por: Nacho Cabanes
Actualizado: 09-08-2020 16:47
Tiempo de lectura estimado: 20 min.

 

Versión en video (13:48 min):

Fund.Prog con Python 2020

08 - Contacto con los arrays o matrices (y las listas)

Vamos a tener un primer contacto breve con las matrices y en el caso de Python hablaremos también de listas, que es un concepto relativamente relacionado, no tanto en otros lenguajes, pero sí en el caso de Python.

La idea básica que hay detrás de las matrices (que en inglés se suelen llamar "arrays" y que algunos algunos autores traducen también como "arreglos") es que con mucha frecuencia no necesitaremos un único dato, sino un conjunto de datos.

Imaginemos, por ejemplo, que yo necesito los datos 5 6, 7, 8, 9.

Podría hacer cosas como decir: mi primer número es un 5. Mi segundo número es un 6. Mi tercer número es un 7. Mi cuarto número es un ocho y así sucesivamente:

n1 = 5
n2 = 6
n3 = 7
n4 = 8
n5 = 9

Pero esto creo que resulta bastante evidente que si con 5 variables ya es trabajoso, si tenemos 100, 1.000 es impensable, y no digamos ya con datos realmente grandes, con un millón o más.

Por eso, lo que queremos es definir un único bloque que almacene todos esos datos. Ese bloque que almacena datos, tipicamente datos que sean del mismo tipo (por ejemplo, todo números o todo nombres) es lo que se suele llamar un "array", un arreglo, un vector, o una matriz.

¿Cómo se hace eso en Python?

Pues en Python y en la mayoría de lenguajes lo que haremos es indicar una serie de datos entre corchetes y separados por comas.

Por ejemplo, yo podría poner mis datos van a ser ... abro un corchete... y aquí pondría 5,6,7,8,9...

datos = [5, 6, 7, 8, 9]

Se pueden dejar espacios entre medias para que sea más legible, pero no es obligatorio.

¿Qué haremos ahora para acceder a cada uno de esos datos? Pues a partir de su posición: el primer dato habitualmente será la posición cero. Es lo que ocurre en Python, pero también lo que ocurre en la mayoría de lenguajes. Con lo cual, si yo pongo que me muestre cuál es el valor de, dentro de mis datos, en concreto, el dato que está en la posición cero, eso me debería decir un 5, que es ese primer dato, el segundo estará en la posición 1, el tercero en la posición 2. Para comprobarlo vamos a decirle ahora que me muestre el dato que está en la posición 2, que insisto, será la tercera:

datos = [5, 6, 7, 8, 9]
print( datos[0] )
print( datos[2] )

También es muy frecuente querer recorrer todos los datos y, para eso, lo más habitual será usar un orden "for", ayudándonos de un "range", como hicimos en la entrega anterior, por ejemplo, yo diría quiero una variable que llamaré, por ejemplo, "i", y que va a tomar sus datos en el rango que va desde, en mi caso, que tengo cinco datos, desde 0 hasta 5. Ya sabes, el 5 no se alcanza, con lo cual tomará los valores 0 1 2 3 4.

for i in range(0, 5):

Pues yo ahora podría decir que quiero que me muestre de mis datos el que está en esa posición "i", con lo cual primero me mostrará el dato que está en la posición cero. Luego el dato que está en la posición 1, luego la 2, luego la 3, luego la 4. Insisto, no se alcanza la posición 5.

for i in range(0, 5):
    print( datos[i] )

Vamos a poner un par de textos adicionales para que quede más claro lo que estamos haciendo. "Datos 0 y 2" y más abajo que "todos los datos":

datos = [ 5, 6, 7, 8, 9]
print("Datos 0 y 2")
print( datos[0] )
print( datos[2] )

print("Todos los datos")
for i in range(0, len(datos)):
  print( datos[ i] )

Y también podríamos, por ejemplo, extraer los datos al revés y en ese caso lo que haríamos es un "range" con un incremento negativo, diría, pues "los datos al revés son":

datos = [ 5, 6, 7, 8, 9]
print("Datos 0 y 2")
print( datos[0] )
print( datos[2] )

print("Todos los datos")
for i in range(0, len(datos)):
  print( datos[ i] )

No pongo acentos porque en algunos entornos concretos puede que te dé un error, si no pones al principio una directiva de "estos caracteres usan tal codificación", pero es un detalle un poco más avanzado que estoy intentando esquivar. Aquí le diría que quiero empezar en la posición 4, ya sabes, la última de esas cinco posiciones, la 4; quiero llegar hasta la -1 sin alcanzarla, porque quiero que alcance la cero y quiero que vaya de -1 en -1.

datos = [ 5, 6, 7, 8, 9]
print("Datos 0 y 2")
print( datos[0] )
print( datos[2] )

print("Todos los datos")
for i in range(0, len(datos)):
  print( datos[ i] )

print("Todos los datos al reves")
for i in range(4, -1, -1):
  print( datos[ i] )

Vamos a comprobarlo.

Datos 0 y 2
5
7
Todos los datos
5
6
7
8
9
Todos los datos al reves
9
8
7
6
5

Primero me dice el dato de la primera posición y el dato de la tercera, posiciones 0 y 2, luego cinco seis siete ocho nueve, que son todos ellos de la posición cero hasta las cinco sin incluir, es decir, de 0 a las 4 y luego desde las 4 hasta la cero, descendiendo, es decir, desde la 4 hacia la -1, sin alcanzarla y con un salto de -1.

Ese es el manejo más habitual de los "arrays", o "arreglos", o "matrices", o vectores, como los quieras llamar. Más adelante profundizaremos más.

Pero realmente en Python esto no es un "array" como tal, porque en la mayoría de lenguajes, a los "arrays" no se les puede cambiar su tamaño. Si yo preparo un "array" como éste, que tenga cinco datos, no podré pasar a tener 6, porque en la mayoría de lenguajes, un "array" es algo estático, tiene un tamaño prefijado y ese tamaño es inmutable.

En Python no es así, yo puedo añadir elementos al final. Con lo cual yo podría aquí decir que quiero, en mis datos añadir uno más, el que sea, por ejemplo, un 15, con ".append":

Pues eso lo que hace, es que ese array se hace un poco más grande. Y añade al final un dato 15.

datos = [ 5, 6, 7, 8, 9]
datos.append(15)

De forma que ya no tiene cinco datos, ya tiene seis. Ese comportamiento, una estructura de datos formada por datos similares, pero que puede ir creciendo, en la terminología de otros lenguaje de programación, es lo que se conoce como una lista, una lista de datos.

Insisto, a nivel de nomenclatura, un "array", un "arreglo", un "vector" tiene el tamaño prefijado; una lista puede ir aumentando su tamaño. Por eso, siendo estrictos, Python lo que tiene, son listas, no arrays, por loque esta operación va a ser válida. Vamos a comprobarlo y veremos que, al lanzar el programa, aquí aparecerá un dato 15 a continuación, y en primer lugar aparecerá también un dato 15. Para que eso sea verdad tendría que cambiar esto de aquí o que indicarle "Llega hasta el final" Primero vamos a cambiarlo a mano, diré "Quiero ir hasta la posición 6 sin alcanzarla" y "quiero empezar en la 5".

datos = [ 5, 6, 7, 8, 9]
datos.append(15)
print("Datos 0 y 2")
print( datos[0] )
print( datos[2] )

print("Todos los datos")
for i in range(0, 6):
  print( datos[ i] )

print("Todos los datos al reves")
for i in range(5, -1, -1):
  print( datos[ i] )

Y vemos que ahora ha aparecido aquí un último dato 15 y un primer dato 15, cuando recorremos al revés:

Datos 0 y 2
5
7
Todos los datos
5
6
7
8
9
15
Todos los datos al reves
15
9
8
7
6
5

Una forma más elegante, insisto, es no poner aquí un 6, sino poner "quiero que vayas hasta la cantidad de datos que tengo". Para esa cantidad de datos, se usa la palabra "len", como abreviatura de "length", longitud.

Si yo pongo, quiero que vayas hasta "len(datos)", lo que hará es: Como tengo cinco datos, más uno 6, esa longitud de mis datos será seis, con lo cual se comportará igual que antes, con la diferencia de que si yo añado un dato más, (por ejemplo, ahora voy a añadir un dato 20), se mostrarán todos ellos.

datos = [ 5, 6, 7, 8, 9]
datos.append(15)
datos.append(20)
print("Datos 0 y 2")
print( datos[0] )
print( datos[2] )

print("Todos los datos")
for i in range(0, len(datos)):
  print( datos[ i] )

print("Todos los datos al reves")
for i in range(5, -1, -1):
  print( datos[ i] )

Vamos a comprobarlo... Verás que en la primera pasada aparece el 20, porque estamos llegando hasta el final y en la descendente no aparece el 20, porque aquí nuestro punto de partida estaba prefijado en la posición 5, que es la sexta.

Datos 0 y 2
5
7
Todos los datos
5
6
7
8
9
15
20
Todos los datos al reves
15
9
8
7
6
5

Hemos visto como mostrar los datos que tomamos de un array, pero no hemos visto cómo crear un array a partir de datos que introduzca al usuario. En algunos lenguajes serían cosas parecidas a estas: decir "datos[5]". Eso en algunos lenguajes sale a ser que mi array, mi arreglo va a contener cinco datos, pero esa sintaxis no es válida en Python.

En Python lo que haremos, es decir "datos es igual a un array vacío":

datos = []

Pero para guardar los datos tampoco podemos hacer cosas: como en la primera posición. quiero que me pongas un 2, porque todavía no existe esa primera posición.

datos = []
datos[0] = 2   # error

Insisto, los arrays en Python se comportan más bien como una lista, como algo que puede ir creciendo. No podemos acceder a las posiciones que todavía no están disponibles, con lo cual lo que haríamos sería decir "en mis datos, quiero que añadas" (y para eso usaremos ".append"), "por ejemplo el dato 3" y en cuanto ya está ese dato en la primera posición, ya sí que podríamos acceder a esa primera posición y cambiar su valor, pero no antes. Primero tendremos que añadir con ".append" y después ya podremos acceder a las posiciones que tenemos

datos = []
datos.append(3)
datos[0] = 2

y recuerda que las posiciones que teníamos las sabemos con "len". Yo podría decir "quiero que me digas cuál es la longitud de mis datos".

datos = []
datos.append(3)
datos[0] = 2
print(len(datos))

Si lo haces, el programa me dirá que hay un dato y que inicialmente ese dato había sido un 3, se ha convertido en un 2, pero no hay más datos que ese primero. Hay un dato y si quiero comprobar su valor, pondría "muéstrame ese dato que hay en la posición cero".

datos = []
datos.append(3)
datos[0] = 2
print(len(datos))
print(datos[0])

Ahí está. Tenemos un único dato y ese dato es un 2. Insisto, inicialmente era un 3, finalmente lo hemos cambiado por un 2.

¿Qué haremos si queremos que el usuario introduzca, por ejemplo, cinco datos? Pues diriamos "quiero usar valores para una variable, por ejemplo, i que va a estar en un rango que empieza en 0 y que no llegue a alcanzar el 6". Y para eso valores le voy a decir que el dato que haya en la posición "i" lo introduzca al usuario.

¿Cual es la forma en que se haría en otros lenguajes? El dato de la posición "i" va a ser igual a, tomado como entero, lo que el usuario teclee como respuesta a "Dime un dato".

datos = []
for i in range(0, 6):
  datos[i] = int(input("Dime un dato "))  # Forma en otros lenguajes, no en Python

Algo así sería la idea en otros lenguajes de programación. El dato cero, en la siguiente pasada el dato 1 y en la siguiente el dato 2, y así hasta llegar a 5. Recuerda, no se alcanza el 6... Será el resultado de pedir al usuario un dato. Pero ya sabes, en Python, no podemos acceder a la posición 0, ni a la 1, ni a la 2, porque no existen todavía.

Si yo intento lanzar esto, fallará. En cuanto accedo a una posición que no está accesible, obtendré el error de "index out of range", índice fuera de rango, me he salido más allá de los índices permitidos en ese array, o, insisto, en esa lista.

¿Cuál es la forma de hacerlo correcta en Python? Decir "pues a mis datos quiero que les añadas Un valor que va a ser eso convertido a entero", lo que el usuario introduzca como respuesta:

datos = []
for i in range(0, 6):
  datos.append( int(input("Dime un dato ")) )

Y vamos después, por ejemplo, a mostrar esos datos, en orden contrario. Haríamos un segundo "for", qué sería para "i" que ahora irá en el rango empezando en 5 hasta casi menos uno. bajando de menos uno menos uno, es decir, cinco cuatro tres dos uno cero y no se alcanza el menos uno. Para esos datos, quiero que me escribas cuanto vale, de mis datos, el que está en la posición "i".

datos = []
for i in range(0, 6):
  datos.append( int(input("Dime un dato ")) )

for i in range(5, -1, -1):
  print(datos[i])

Así, primero leemos los datos y luego los mostramos al revés.

Esta será la forma habitual de pedir datos al usuario en nuevas posiciones del array y ya sabes, si queremos cambiar cualquiera de ellos, diríamos "de mis datos, el de la posición 2 va a ser, por ejemplo, en este caso -5".

datos[2] = -5

El programa completo podría ser:

datos = []
for i in range(0, 6):
  datos.append( int(input("Dime un dato ")) )

datos[2] = -5

for i in range(5, -1, -1):
  print(datos[i])

Si lo volvemos a lanzar ahora verás que en la tercera posición en vez de haber un 30, habrá un -5.

Dime un dato 10
Dime un dato 20
Dime un dato 30
Dime un dato 40
Dime un dato 50
Dime un dato 60
60
50
40
-5
20
10

10, 20, 30, 40, 50, 60... Y efectivamente, en la tercera posición ya no hay un 30, sino un -5.

Volveremos a los "arrays" más adelante, pero en la próxima entrega nos dedicaremos a las cadenas de texto, que tienen muchas cosas en común con los "arrays".

Ejercicio propuesto 8.1. Crea un array con los números 10, 20, 30, 40, 50 y luego muestra los que hay en las posiciones impares (primero, tercero y quinto: 10, 30 y 50).

Ejercicio propuesto 8.2. Pide al usuario 10 números y luego muestra los que son pares.

Ejercicio propuesto 8.3. Pide al usuario un número entero del 1 al 12 y escribe el nombre del mes correspondiente (1=enero, 12=diciembre), usando un array.

70 visitas desde el 09-08-2020

AnteriorPosterior