2. Arrays
Los escalares sirven para almacenar “una cosa
de algo”
Los arrays son una forma de almacenar “muchas
cosas de algo”
Definiciones:
Lista: colección ordenada de escalares
Array: variable que contiene una lista
3. Arrays
Los arrays/listas están ordenados, es decir, tienen
una determinada secuencia.
Los array/listas están indexados por enterors
empezando en cero
Dado que los arrays son listas de escalares, pueden
almacenar indistintamente cadenas o números.
Pueden tener cualquier número de elementos. El
límite lo pone la memoria disponible.
4. Arrays: accediendo a sus
elementos
1.$marcas[0] = "Ford";
2.$marcas[1] = "Mercedes";
3.$marcas[2] = "Kia";
El “nombre” de este array es marcas.
Podemos tener en el mismo script un escalar $marcas y un
array marcas.
El índice es un número, por lo que podemos acceder usando
$marcas[$indice - 4]
¿Qué mostrará por pantalla say $marcas[‘3rosas’ - 2];?
5. Arrays: accediendo a sus
elementos
1.$marcas[0] = "Ford";
2.$marcas[1] = "Mercedes";
3.$marcas[2] = "Kia";
El “nombre” de este array es marcas.
Podemos tener en el mismo script un escalar $marcas y un
array marcas.
El índice es un número, por lo que podemos acceder usando
$marcas[$indice - 4]
¿Qué mostrará por pantalla say $marcas[‘3rosas’ - 2];?
Mercedes
6. Arrays
¿qué pasa si nos salimos de los límites del
array?
1.$marcas[0] = "Ford";
2.$marcas[1] = "Mercedes";
3.$marcas[2] = "Kia";
4.$marcas[100] = "Toyota";
7. Arrays
¿qué pasa si nos salimos de los límites del
array?
1.$marcas[0] = "Ford";
2.$marcas[1] = "Mercedes";
3.$marcas[2] = "Kia";
4.$marcas[100] = "Toyota";
Se crean 98 elementos y se les asigna el valor
undef
9. Arrays: último índice
1.$indice = $#marcas; #índice del último elemento, 100
2.$elementos = $indice + 1; #hay 101 elementos
3.$marcas[$#marcas] = “Honda” # Sobreescribimos el último
# elemento
10. Arrays: último índice
1.$indice = $#marcas; #índice del último elemento, 100
2.$elementos = $indice + 1; #hay 101 elementos
3.$marcas[$#marcas] = “Honda” # Sobreescribimos el último
# elemento
Como acceder al último elemento es algo que
ocurre muy a menudo, perl nos da un “atajo” usar
íncides negativos
1.$marcas[-1] #Devuelve Honda
2.$marcas[-101] #Devuelve el primer elemento
3.$marcas[-200] = “Honda” # Error
11. Arrays: literales de lista
(1, 3, 5, 7)
(“nombre”, 3, 5.5, “López”)
() #Lista vacía
(1..100) # lista de 100 enteros usando el operador de
rango
(5..1) #lista vacía (no funciona hacia abajo)
($n..$m)
(0..$#marcas)
($n+10..$p+$q)
(‘maría’, ‘mariano’, ‘luis’, ‘rodrigo’, ‘ana’)
12. Arrays: qw
En lugar de
(‘maría’, ‘mariano’, ‘luis’, ‘rodrigo’, ‘ana’)
podemos hacer lo siguiente
qw( maría mariano luis rodrigo ana )
Cada “palabra” se trata como una cadena entre
comilla simple, así que no podemos usar
secuencias de escape o interpolación de variables
14. Arrays: qw
Podemos usar cualquier delimitador
qw! maría mariano luis rodrigo ana !
qw# maría mariano luis rodrigo ana #
Podemos usar también los siguientes “pares” de
delimitadores
qw{ maría mariano luis rodrigo ana }
qw[ maría mariano luis rodrigo ana ]
qw< maría mariano luis rodrigo ana >
Si necesitamos incluir el delimitador tenemos que
escaparlo:
qw! google msn yahoo! apple !
15. Arrays: asignación de
listas
Asignar los valores de una lista a un conjunto de
variables:
($nombre, $apellido1, $apellido2) = (‘Luis’,
‘López’, ‘Pérez’);
Podemos intercambiar valores
($admin, $superadmin) = ($superadmin, $admin)
16. Arrays: asignación de
listas
¿Qué pasa si el número de elementos no coincide?
($nombre, $apellido1) = qw( luis López Pérez)
El “Pérez” de la derecha se descarta.
($nombre, $apellido1, $apellido2) = qw( luis López )
$apellido2 vale undef.
18. Arrays: asignación de
listas
¿y si queremos asignar la lista a un array?
($users[0], $users[1], $users[2]) = qw/ pilar pepe pedro /
19. Arrays: asignación de
listas
¿y si queremos asignar la lista a un array?
($users[0], $users[1], $users[2]) = qw/ pilar pepe pedro /
En lugar de esto podemos utilizar lo siguiente
@users = qw/ pilar pepe pedro /
20. Arrays: asignación de
listas
Más asignaciones de lista a array
@usuarios = qw/ user1 user2 user3 /
@enteros = (1..100)
@todos = (@usuarios, @administradores)
@cosas = (@ususarios, ‘cadena’, entero,
$variable)
21. Arrays: asignación de
listas
Muy importante:
@todos = (@usuarios, @administradores)
no es un array de arrays, es la “concatenación” de dos arrays.
@todos contiene los elementos de @usuarios seguidos de los
elementos de @administradores
Copia de arrays:
@copia = @todos
En realidad esto es una asignación de listas (@todos se
expande a lista y se asigna a @copia)
22. Arrays: funciones y
operadores
pop: quita un elemento del array por el final
push: añade un elemento al array por el final
unshift: saca un elemento del array por el
principio
shift: añade un elemento al array por el
principio
23. Arrays: funciones y
operadores
splice: sirve para obtener “rebanar” de un array
25. Arrays: funciones y
operadores
1.@picapiedra = qw( pablo pedro betty wilma dino );
2.@borrado = splice @array, 2; # se borra todo después de
26. Arrays: funciones y
operadores
1.@picapiedra = qw( pablo pedro betty wilma dino );
2.@borrado = splice @array, 2; # se borra todo después de
1.@picapiedra = qw( pablo pedro betty wilma dino );
2.@borrado = splice @array, 1, 2; # se borran los elementos
27. Arrays: funciones y
operadores
1.@picapiedra = qw( pablo pedro betty wilma dino );
2.@borrado = splice @array, 2; # se borra todo después de
1.@picapiedra = qw( pablo pedro betty wilma dino );
2.@borrado = splice @array, 1, 2; # se borran los elementos
1.@picapiedra = qw( pablo pedro betty wilma dino );
2.@borrado = splice @array, 1, 2, qw(NUEVO); # se borran los
# elementos pedro y betty y en su lugar se
# añade NUEVO
29. Arrays: interpolación en
cadenas
1.@picapiedra = qw( pablo pedro betty wilma dino );
2.say “Los picapiedra son @picapiedra”;
-----
Los picapiedra son: pablo pedro betty wilma dino
30. Arrays: interpolación en
cadenas
1.@picapiedra = qw( pablo pedro betty wilma dino );
2.say “Los picapiedra son @picapiedra”;
-----
Los picapiedra son: pablo pedro betty wilma dino
1.@picapiedra = qw( pablo pedro betty wilma dino );
2.say “mi email es pedro@picapiedra.com”;
-----
mi email es pedropablo pedro betty wilma dino.com
31. Arrays: interpolación en
cadenas
1.@picapiedra = qw( pablo pedro betty wilma dino );
2.say “mi email es pedro@picapiedra.com”;
-----
mi email es pedropablo pedro betty wilma dino.com
32. Arrays: interpolación en
cadenas
1.@datos = qw( pablo pedro betty wilma dino );
2.$datos = “ESCALAR”
3.print "$datos[3]n"; # imprime $datos[3] -> wilma
4.print "${datos}[3]n"; # imprime "ESCALAR[3]"
#(protegido por los corchetes)
5.print "$datos"."[3]n"; # imprime ESCALAR[3]
6.print "$datos[3]n"; # imprime ESCALAR[3], el corchete está
# escapado
33. Arrays: foreach
Estructura de control que itera sobre todos los
elementos del array
1.@datos = qw( pablo pedro betty wilma dino );
2.foreach $dato (@datos) {
3. print "El personaje es $dato.n";
4.}
En cada iteración, la variable $dato almacena
uno de los elementos del array.
34. Arrays: foreach
La variable $dato NO es una copia del elemento
del array, por lo que si se modifica en el bucle,
se modifica el array.
El valor de la variable de control después del
bucle recupera el valor que tenía antes.
35. Arrays: foreach
La variable $dato NO es una copia del elemento
del array, por lo que si se modifica en el bucle,
se modifica el array.
El valor de la variable de control después del
bucle recupera el valor que tenía antes.
...pero esto son muchos caracteres que escribir
¿no era perl un lenguaje conciso?
36. Arrays: foreach
1.#Vamos a hacerlo más corto. No necesitamos el array datos
2.foreach $dato ( qw( pablo pedro betty wilma dino ) ) {
3. print "El personaje es $dato.n";
4.}
5.
6.#No necesitamos la variable $dato, podemos usar $_
7.foreach ( qw( pablo pedro betty wilma dino ) ) {
8. print "El personaje es $_.n";
9.}
10.
11.#Dado que sólo tenemos una instrucción dentro del bucle
podemos hacer lo siguiente
12.print "El personaje es $_.n" foreach ( qw( pablo pedro
betty wilma dino ) );
37. Arrays: sort y reverse
sort: Devuelve un array con los elementos
ordenador por orden alfabético
@ordenado = sort (@array)
@numeros = sort 97..110
reverse: Devuelve un array con los elementos en
orden inverso
@reves = reverse @array
38. Arrays: each
A partir de la versión 5.12 de perl, es posible
usar la función each con arrays (antes sólo se
podía con hashes)
1.use 5.012;
2.#Recorriendo un array con each
3.my @datos = qw( pablo pedro betty wilma dino );
4.while(my($indice,$valor) = each @datos) {
5. say "$indice: $valor";
6.}
7.#Si no podemos usar each, tenemos que hacerlo con foreach
8.@datos = qw( pablo pedro betty wilma dino );
9.foreach my $indice (0..$#datos) {
10. say "$indice: $datos[$indice]";
11.}
39. Arrays: for
1.@datos = qw( pablo pedro betty wilma dino );
2.for($i = 0; $i < $#datos; $i++ ) {
3. say "$i: $datos[$i]";
4.}
45. Contextos
Que sea importante no quiere decir que sea difícil. Veamoslo
Dada una expresión, esta puede significar cosas diferentes
en función de cómo y dónde se usa
46. Contextos
Que sea importante no quiere decir que sea difícil. Veamoslo
Dada una expresión, esta puede significar cosas diferentes
en función de cómo y dónde se usa
Esto no es para vosotros un concepto nuevo ni mucho
menos. Por ejemplo:
47. Contextos
Que sea importante no quiere decir que sea difícil. Veamoslo
Dada una expresión, esta puede significar cosas diferentes
en función de cómo y dónde se usa
Esto no es para vosotros un concepto nuevo ni mucho
menos. Por ejemplo:
Me LARGO de aquí
48. Contextos
Que sea importante no quiere decir que sea difícil. Veamoslo
Dada una expresión, esta puede significar cosas diferentes
en función de cómo y dónde se usa
Esto no es para vosotros un concepto nuevo ni mucho
menos. Por ejemplo:
Me LARGO de aquí
Que día tan LARGO
49. Contextos
Que sea importante no quiere decir que sea difícil. Veamoslo
Dada una expresión, esta puede significar cosas diferentes
en función de cómo y dónde se usa
Esto no es para vosotros un concepto nuevo ni mucho
menos. Por ejemplo:
Me LARGO de aquí
Que día tan LARGO
Si te pregunto por el significado de la palabra LARGO tu
respuesta dependerá del contexto.
50. Contextos
Ya hemos visto un ejemplo de contextos:
2*3=6
2 x 3 = 222
El operador define el contexto de la expresión
y, en función de este, se trata 2 y 3 como
cadenas o como números.
51. Contextos
Cuando perl analiza una expresión siempre espera un
escalar o una lista.
Una expresión siempre devuelve el valor apropiado según el
contexto en el que se evalúe
Veamos qué significa esto con un ejemplo:
¿Qué significa la expresión @datos?
En un contexto de lista es la lista de elementos del array
En un contexto escalar significa el número de elementos
del array
52. Contextos
1.@datos = qw( pablo pedro betty wilma dino );
2.$ordenados = sort @datos # contexto lista: sort espera
# una lista
3.$valor = 45 + @datos # contexto escalar: el operador +
# opera sobre escalares.
# $valor valdrá 50
4.$valor = @datos # contexto escalar: asignación a un escalar.
# $valor valdrá 5
53. Contextos
¿Qué ocurre si intentamos utilizar una expresión que
genera una lista en un contexto escalar?
Por ejemplo: reverse @array
Es una expresión que genera una lista con los
elementos del array en orden inverso
@resultado = reverse qw( elem1 elem2 elem3 )
¿y si hacemos lo siguiente?
$resultado = reverse qw( elem1 elem2 elem3 )
¿Qué vale resultado?
54. Contextos
¿Qué ocurre si intentamos utilizar una expresión que
genera una lista en un contexto escalar?
Por ejemplo: reverse @array
Es una expresión que genera una lista con los
elementos del array en orden inverso
@resultado = reverse qw( elem1 elem2 elem3 )
¿y si hacemos lo siguiente?
$resultado = reverse qw( elem1 elem2 elem3 )
¿Qué vale resultado?
3mele2mele1mele
55. Contextos
¿Y porqué devuelve eso y no otra cosa?
Devuelve eso porque el sentido común de Larry
Wall determinó en su día que eso era así.
Hasta que aprendamos a tener el sentido común
de Larry, tendremos que mirar la
documentación:
perldoc -f reverse
perldoc -f sort
56. Contextos
¿Qué ocurre si intentamos utilizar una
expresión que genera un escalar en un
contexto de lista?
Se genera una lista de un único
elemento:
1.@array = 6 * 7; # Se crea un array de un elemento (42)
2.@array = "hola" . ' a ' . "todos";
57. Contextos
Cuidado con la siguiente expresión:
1.@array = undef; # Se genera un array de un elemento undef
# (undef)
2.say "elementos: $#array";
3. @array = (); #Esto es un array de cero elementos
4.say "elementos: $#array";
58. Contextos
A veces podemos necesitar forzar un contexto
escalar donde perl espera una lista
1.@picapiedra = qw( pablo pedro betty wilma dino );
2.print "¿cuántos son los picapiedra?n";
3.say "Los picapiedra son ", @picapiedra ;
# MAL, imprime los nombres
4.say "los picapiedra son ", scalar @picapiedra;
# Correcto, da el número de elementos del array
59. Contextos: <STDIN>
En contexto de lista, este operador devuelve
todas las líneas de entrada en un array
1.@lines = <STDIN>; # Lee todas las líneas de la entrada
# estándar
60. Contextos: <STDIN>
Si la entrada viene de un fichero, se lee todo el
fichero en memoria.
Cuando se lee el fichero, se leen también los
caracteres de fin de línea. Podemos utilizar
chomp en contexto de lista para quitarlos
1.@lines = <STDIN>;
2.chomp (@lines);
61. Contextos: <STDIN>
Si la entrada viene de un fichero, se lee todo el
fichero en memoria.
Cuando se lee el fichero, se leen también los
caracteres de fin de línea. Podemos utilizar
chomp en contexto de lista para quitarlos
1.chomp(@lines = <STDIN>);
62. Ejercicios
1. Escribe un programa que pida al usuario una lista de cadenas en líneas separadas y las
imprima en orden inverso a como se han leído.
2. Escribe un programa que lea una lista de números (cada uno en una línea) hasta un EOF
e imprima el nombre de la persona asociada a cada número de la siguiente lista:
mariana, luis, miguel, ramón, rosalía, juan, pablo, natalia
3. Implementar una pila (first in, first out) en perl. Dar al usuario las siguientes opciones:
1. Añadir elemento a la pila
2. Sacar elemento de la pila
3. Imprimir pila
4. Salir
Notas del editor
\n
Recordar:\n- Cada elemento de la lista o del array es un escalar, esto es importante para ver c&#xF3;mo trabajamos con los elementos dentro de un programa\n\n
En realidad no pueden tener cualquier tama&#xF1;o ya que el &#xED;ndice es un entero con signo. Eso signfica que s&#xF3;lo pueden tener 2,147,483,647\n\nEjercicio: escribir un script en perl que imprima este n&#xFA;mero\nperl -e 'print 0x7FFFFFFF."\\n"'\n
Poner el ejemplo arrays1.pl\n\n#!/opt/local/bin/perl\n# Este gui&#xF3;n muestra c&#xF3;mo podemos tener un escalar y un array con el mismo nombre\nuse 5.010;\nuse utf8;\nuse warnings;\n\n$marcas = "ESCALAR marcas";\n\n$marcas[0]="Ford";\n$marcas[1]="Mercedes";\n$marcas[2]="Kia";\n\n\nsay $marcas;\nsay "Mi coche es un $marcas[1]";\n\n#Los &#xED;ndices son enteros, por lo que podemos usar escalares para acceder a ellos\n$indice=2;\nsay "Mi coche es un $marcas[$indice]";\n\n#Aunque esta l&#xED;nea muestra un warning, es\nsay "Mi coche es un ".$marcas['3rosas' - 2];\n
Poner el ejemplo arrays1.pl\n\n#!/opt/local/bin/perl\n# Este gui&#xF3;n muestra c&#xF3;mo podemos tener un escalar y un array con el mismo nombre\nuse 5.010;\nuse utf8;\nuse warnings;\n\n$marcas = "ESCALAR marcas";\n\n$marcas[0]="Ford";\n$marcas[1]="Mercedes";\n$marcas[2]="Kia";\n\n\nsay $marcas;\nsay "Mi coche es un $marcas[1]";\n\n#Los &#xED;ndices son enteros, por lo que podemos usar escalares para acceder a ellos\n$indice=2;\nsay "Mi coche es un $marcas[$indice]";\n\n#Aunque esta l&#xED;nea muestra un warning, es\nsay "Mi coche es un ".$marcas['3rosas' - 2];\n
\n
Todo esto est&#xE1; en el ejemplo arrays2.pl\n
Todo esto est&#xE1; en el ejemplo arrays2.pl\n
Todo esto est&#xE1; en el ejemplo arrays2.pl\n
\n
\n
\n
&#xBF;por qu&#xE9; tanta flexibilidad? Imaginad que necesitamos crear una lista como esta\nqw{/usr/dict/words\n/home/rootbeer/.ispell_english\n}\n\ny s&#xF3;lo tuvi&#xE9;semos el delimitador /. Tendr&#xED;amos que estar escapando todo el rato y, adem&#xE1;s, no ser&#xED;a muy legible\n\n
Esto del intercambio de puede hacer porque la lista de la derecha se construye antes de la asignaci&#xF3;n y por lo tanto conserva los valores originales\n
\n
\n
\n
Importante:\n@todos el nombre de un array se expande a la lista que contiene, por eso un array tal cual lo hemos definido no puede formar parte de otro array y @todos se convierte en la &#x201C;suma&#x201D; de dos arrays. \n\nVeremos como gestionar esto cuando trabajemos con dependencias.\n
\n
ver el ejemplo arrays_poppush.pl\n
\n
\n
\n
\n
ejemplo: arrays_interpolacion.pl\n\nGenera un listado de elementos separados por espacios.\n\nCuidado con la interpolaci&#xF3;n\n\n\n
ejemplo: arrays_interpolacion.pl\n\nGenera un listado de elementos separados por espacios.\n\nCuidado con la interpolaci&#xF3;n\n\n\n
ejemplo: arrays_interpolacion.pl\n
ejemplo: arrays_interpolacion.pl -> este c&#xF3;digo est&#xE1; ah&#xED; metido\n
ejemplo: arrays_foreach.pl -> este c&#xF3;digo est&#xE1; en ese fichero\n
ejemplo: arrays_foreach.pl -> esto est&#xE1; en ese ejemplo\n
ejemplo: arrays_foreach.pl -> esto est&#xE1; en ese ejemplo\n
ejemplo: arrays_foreach.pl -> esto est&#xE1; en ese ejemplo\n
\n
Ojo con el ejemplo: los elementos est&#xE1;n ordenados por ascii no por valor!!!\n
El ejemplo est&#xE1; en arrays_each.pl\n\nExplicar c&#xF3;mo funciona: en cada llamada a each se devuelve una pareja &#xED;ndice/valor\n
Esto est&#xE1; en el ejemplo arrays_for.pl \n
Si esto lo entend&#xE9;is bien, sacar&#xE9;is el m&#xE1;ximo partido a Perl.\n
Si esto lo entend&#xE9;is bien, sacar&#xE9;is el m&#xE1;ximo partido a Perl.\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
Ejecutar estos dos comandos y ver qu&#xE9; hace sort en contexto escalar\n
esto est&#xE1; en contexto2.pl\n
esto est&#xE1; en contexto2.pl\n\nLa manera correcta de generar un array de cero elementos es @array = ();\n
\n
\n
- Limite: memoria y n&#xFA;mero de l&#xED;neas, recordad que tenemos un m&#xE1;ximo de &#xED;ndices.\n\n
- Limite: memoria y n&#xFA;mero de l&#xED;neas, recordad que tenemos un m&#xE1;ximo de &#xED;ndices.\n- Para dejar de leer l&#xED;neas:CTRL+D en unix CTRL+Z en windows\n- ejecutar el ejemplo contexto4.pl < contexto4.txt\n\n