¡Ya estamos en Twitter!

Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad

Usando el hash

por Uriel Lizama

Introducción

Los arreglos asociativos de perl son útiles estructuras de datos, que te permiten asociar un pedazo de dato (llamado llave) con otro (su valor). En este tutorial, revisaremos los arreglos asociativos y nos introduciremos a sus usos más avanzados.

Debido a que el nombre Arreglo Asociativo es muy largo, de aquí en adelante y en todos los demás tutoriales que haga, usare el término en inglés hash con su plural hashes.

Asignando pares llave/valor

Los hashes consisten de una o más llaves individuales y su valor asociado. Cada llave y valor son llamados pares. Hay varios métodos de insertar estos pares en un hash.

Si conoces (por lo menos unos) de los pares llave/valor que quisieras usar, lo siguiente es el método más directo para asignar pares a un hash:

%hash = ( manzanas => 6,
naranjas => 5,
peras => 3,
uvas => 2, );

Lo de arriba es la manera más legible de asignar un par llave/valor.

NOTA: No olvidemos la importancia de tener codigo fácil de leer. Una manera menos legible de asignar un valor es así:
%hash = qw(manzana 6 naranjas 5 peras 3 uvas 2);

Perl automáticamente convertira lo anterior a un par llave/valor como si hubieras utilizado las flechas "=$gt;" en el primer ejemplo. Sin embargo recomiendo el formato del primer ejemplo por própositos de legibilidad, aunque puedes usar cualquiera de los formatos.

También puedes agregar cada par llave/valor individualmente. La linea siguiente agrega un nuevo par llave/valor a nuestro hash original:

$hash{durazno} = 3;

Si el hash original no hubiera existido esta linea hubiera creado uno nuevo, e insertado el primer par llave/valor como fue definido. Este proceso en la cual la variable puede brotar a vida, se llama "autovificación".

Esto es útil cuando necesitas hacer un loop a través de un archivo y quisieras insertar los datos del archivo al hash:

open (FILE, "fruits.txt");

while (){
chomp;

my @line = split(/\t/);

$hash{$linea[0]} = $linea[1];

}

close(FILE);


Quitando pares del hash

Ahora que ya sabemos como agregar pares a hashes, necesitamos saber como deshacernos de ellos. Quitando un par es tan fácil como saber el par que quieres borrar:

delete $hash{durazno};

Ahora, el para cuya llave es durazno ya no existe. ¿Pero qué pasa si quieres borrar todo el hash?. Podrías hacer un loop por todo el hash y borrar cada llave (ineficiente) o podrías hacerle undef:

undef %hash;

No uses:

%hash = undef;

Esto no desdefinaría al hash, asignaría un nuevo par llave/valor de undef/undef. Si quisieras quitar todas las llaves del hash y aún mantener "%hash" como una variable activa, usa:

%hash = ();

Mirando dentro del hash

Ahora ya sabemos como agregar y quitar pares del hash. Pero ¿cómo vemos los pares dentro de él?

Como en todas las cosas en Perl, HMDUMPH (hay más de una manera para hacerlo). Aquí, veremos unos ejemplos de como hacer un loop dentro de los hashes y hechar un vistazo a lo que hay dentro.

Usando foreach

foreach my $llave (keys %hash){
print "$llave = $hash{$llave}\n";
}

La variable "my $llave" localiza la variable escalar dentro del loop y previene el error "variable no inicializada" cuando se corre con precauciones(warnings).

Usando map

print map "$_ = $hash{$_}\n", keys %hash

Usando while/each

while (($llave,$valor) = each %hash){
print "$llave = $valor\n";
}

Acomodando hashes

Si probaste los ejemplos anteriores, habrás notado que los hashes se imprimen algo así como en orden aleatorio. Esto es porque los hashes son guardados basandose en la locación de memoria, no alfabeticamente ni numericamente. Pero ten fé, es fácil acomodar hashes.

Hay tres maneras de acomodar en perl: ASCIIbeticamente, númericamente o alfabeticamente.

Cada carácter (número, letra o metacarácteres) tiene un codigo ASCII asociado con él.

Las letras tiene codigo ASCII separado por su tipo (minuscula o capital).

Por ejemplo, la letra "A" es 065 y la letra "a" es 097. Entonces A es "menos que" a (065 < 097).
Con esto en mente, creemos un sencillo hash que use de los dos tipos, minusculas y capitales en sus llaves:

%hash = (Manzanas => 1, manzanas => 4, alubias => 5, Frijoles => 9);

foreach my $llave (sort keys %hash){

print "$llave = $hash($llave}\n";

}

Para poder ordenar los hashes sin importar el tipo de letra, hay que hacer todas las letras minúsculas y después compararlas:

%hash = (Manzanas => 1, manzanas => 4, alubias => 5, Frijoles => 9);

foreach my $llave (sort {lc($a) cmp lc($b)} keys %hash){

print "$llave = $hash($llave}\n";

}

Esto imprimira correctamente el hash en orden alfabetico.

Rebanadas de hash

Una rebanada es una sección o número de elemetos de una lista, array o hash. Esencialmente, puedes agregar o borrar pares de llave/valor en masa usando rebanadas, que son nombradas usando el símbolo de "@". Para dar un ejmplo de rebanadas, consideremos lo siguiente:

@meses = qw(Ene Feb Mar Abr May Jun Jul Ago Sep Oct Nov Dic);
@numMeses{ @meses } = 1..$#meses+1;

Aquí, hemos creado un hash llamado %numMeses usando una rebanada de hash. Agrego cada elemento del array "@meses" como llaves, y los números 1 hasta el 12 a cada valor del mes. Porque @meses esta en orden, agregando 1 al 12 asigna el valor correcto a cada llave.

Pues, has creado una rebanada de hash, ahora queremos imprimir el resultado para ver si es correcto.

foreach my $llave( sort {$numMeses{$a} <=> $numMeses{$b}} keys %numMeses){
print "$llave = $numMeses{$llave}\n";
}

Ya habíamos visto como ordenar los hashes anteriormente, y solo lo agregamos, para ordenar el hash de una manera númerica. Usando los valores en vez de las llaves.

Functionando el orden

Cuando uno trabaja mucho con el ordenamiento de los hashes, llega a haber muchos problemas debido a que debes de teclear todo una y otra vez. Entonces vamos a ver una buena opción, creemos funciones para el ordenamiento.

Este es un ejemplo:

foreach my $llave (sort alfa_bajo keys %hash){
print "$llave = $hash{$llave}\n";
}

Vemos que hemos sustituido lo de $a y $b por una llamada de funcion. Ahora veamos las funciones:

sub num_bajo {$a <= $b}
sub num_arriba {$b <= $a}
sub alfa_bajo {lc($a) cmp lc($b)}
sub alfa_arriba {lc($b) cmp lc($a)}
sub alfanum_bajo {$a <= $b || lc($a) cmp lc($b)}
sub alfanum_arriba {$b <= $a || lc($b) cmp lc($a)}

Las funciones "alfanum_bajo" y "alfanum_arriba" ordenan alfabeticamente y númericamente.

Ordenando por valores

¿Qué pasaría si quisieras acomodar por medio de valores en vez de por llaves? Usando el hash de los primeros ejemplos podemos considerar lo siguiente:

%hash = (Manzanas => 1, manzanas => 4, alubias => 5, Frijoles => 9);

foreach my $llave (sort {$hash{$a} <= $hash{$b}} keys %hash){
print "$llave = $hash{$llave}\n";
}

Esto imprimiría los valores así:

Manzanas = 1 manzanas = 4 Frijoles = 9 alubias = 5

Pero digamos que tuvieramos uno con valores de texto - cambiemos el valor $hash{'alubias'} a "Latas: 15 - 20 g." y $hash{'Manzanas'} a "Rojas Deliciosas - 6 tamaño grande".

Podemos hacer que el hash las acomodode númericamente y alfabeticamente usando el siguiente codigo:

%hash = (Manzanas => 1, manzanas => 4, alubias => 5, Frijoles => 9);

$hash{'alubias'} = "Latas: 15 - 20 g.";
$hash{'Manzanas'} = "Rojas Deliciosas - 6 tamaño grande";

foreach my $llave (sort {$hash{$a} <= $hash{$b} || $hash{$a} cmp $hash{$b}} keys %hash){

print "$llave = $hash{$llave}\n";

}

Esto correctamente imprimiría:


alubias = Latas: 15 - 20 g.
Manzanas = Rojas Deliciosas - 6 tamaño grande
manzanas = 4
Frijoles = 9

Hashes de dimendiones multiples

Usar pares de llave/valor es sumamente grandioso, pero...¿qué si quisieramos asociar más de un valor a una llave?. Usando una construcción un poco diferente, esencialmemente puedes usar arrays como un valor de llave:

%hash = ( Manzanas = [4, "Rojas Grandes", "medianas"], "Café Colombiano" = [1, "paquete", "1/2 kilo"], anchoas = [3, "latas", "300 g."], Limoes = [6, "Verdes", "chicos"], "3 Ríos" = [1, "Jabón", "botellas"], "89 Ferd" = [1, "paquete", "1 kilo"], );

Ahora, a extraer los valores, los puedes tratar como un array de hash (hehe, no se si me entienda):

print $hash{"Café Colombiano"}[1];

Esto imprimiría "paquete", debido a que "paquete " es el segundo elemento del array Café Colombiano. Tambíen puedes agregar un valor pre-definido a un valor del hash:

@cosasVerdes = (4, "espinacas", "grandes");

$hash{"Verduras"} = [@cosasVerdes];

print $hash{"Verduras"}[1]; # imprime espinacas

Y eso es todo para este tema.

¿Quiéres más tutoriales como este? Escribir tutoriales toma una gran cantidad de tiempo y esfuerzo. Si este tutorial te ayudó a aprender o a solucionar algo, por favor considera dejar alguna donación en apoyo a Perl en Español.

Cliquea en el botón de abajo para dejar tu donación por medio de PayPal.

Comparte:
Categorías de Tutoriales:
En Nuestros Foros:

    Software error:

    junk after document element at line 1, column 32, byte 32 at /usr/lib64/perl5/vendor_perl/XML/Parser.pm line 187.
    

    For help, please send mail to the webmaster ([email protected]), giving this error message and the time and date of the error.

  • Entra a los foros »
Socializa:
Síguenos por Twitter

Suscríbete GRATUITAMENTE al Boletín de Perl en Español

Perl en Español es mantenido con Movable Type
Todo el contenido de Perl en Español está bajo una licencia CC:
Creative Commons License