Como pasar de хешу en Perl

La tarea. En el código de Perl programa tiene un hash %h. En este хеше hay algunos pares de valores. Es necesario ir a por todos los elementos de hash y seguir los pasos con cada elemento.

Caminar por хешу con foreach

A menudo, la forma más conveniente para evitar el hash es utilizar foreach. He aquí un ejemplo de código:

▶ Run
#!/usr/bin/perl

my %h = (
    a => 1,
    b => 20,
    asdf => 'Hello',
);

foreach my $key (keys %h) {
    print "$key - $h{$key}\n";
}

Aquí todo es bastante simple. Primero creamos el hash %h en el que hay tres pares de valores. Más allá se encuentra el ciclo. Con la ayuda de keys %h nos ha dado una lista de todas las claves hash (en este ejemplo es la cadena 'a', 'b' y 'asdf'). La cadena con la llave se coloca en la variable $key y se ejecuta el cuerpo del bucle, y luego en $key se añade el siguiente clave hash y de nuevo se ejecuta el cuerpo del bucle, y así ocurre con todas las claves.

Si guardar el código en un archivo script.pl y realizar su perl script.pl, en la pantalla aparecerá el conjunto de pares de valores, las que figuran en el хеше:

b - 20
asdf - Hello
a - 1

El hash es un desordenado conjunto de pares de valores. Y la conclusión es bien visible — el orden en el que fueron retirados los elementos de hash no coinciden con el orden en que se han definido en el código del programa. Y si ejecutar este script varias veces, el orden de los elementos en la salida va a cambiar. keys %h devuelve una lista de claves hash en un orden aleatorio. Si desea que el orden era siempre el mismo, para ello, por ejemplo, se puede utilizar la ordenación foreach my $key (sort keys %h) {.

Pasar por хешу con while y each

Otro método para evitar todo el hash es usar el ciclo de while y la palabra clave each. Aquí está el código que funciona tan bien como el ejemplo anterior:

▶ Run
#!/usr/bin/perl

my %h = (
    a => 1,
    b => 20,
    asdf => 'Hello',
);

while (my ($key, $value) = each %h) {
    print "$key - $value\n";
}

each %h devuelve una lista de dos elementos — clave de hash y valor. De la misma manera, como en el caso de keys el orden en el que each devuelve el par de valores no está definido. Diferentes ejecuciones de la misma el programa devolverá pares de diferentes rangos.

Asignamos los valores que devolvió each en variables. each recuerda que los pares de hash él ya daba y la próxima vez que devolverá otro par de valores. Así continuará hasta que each no volverá a todas las parejas, después de esto, se devuelve una lista vacía. Hasta each devuelve el par de valores está en el cuerpo while del ciclo, tan pronto como se devuelve una lista vacía, el ciclo de whilefinaliza.

El cambio de valores en хеше

Cuando se utiliza foreach del ciclo, keys %h se ejecuta sólo una vez. Cuando se utiliza whileciclo each se realiza en cada iteración.

Extendemos la tarea anterior — necesitamos no sólo la salida de todos los elementos de hash, pero aún y reemplazarlos. Esto es totalmente sin problemas se puede hacer con el uso de foreach y keys:

▶ Run
#!/usr/bin/perl

use Data::Dumper;

my %h = (
    a => 1,
    b => 20,
    asdf => 'Hello',
);

foreach my $key (keys %h) {
    print "$key - $h{$key}\n";
    $h{ $key . $key } = $h{$key};
    delete $h{$key};
}

print Dumper \%h;

La salida del programa:

asdf - Hello
a - 1
b - 20
$VAR1 = {
          'bb' => 20,
          'aa' => 1,
          'asdfasdf' => 'Hello'
        };

Pero no funciona así hacer al utilizar each:

▶ Run
#!/usr/bin/perl

use Data::Dumper;

my %h = (
    a => 1,
    b => 20,
    asdf => 'Hello',
);

while (my ($key, $value) = each %h) {
    print "$key - $value\n";

    # error!
    $h{ $key . $key } = $value;
    delete $h{$key};
}

print Dumper \%h;

Cuando se ejecuta este programa en la pantalla aparecerá algo como esto:

Use of each() on hash after insertion without resetting hash iterator results in undefined behavior at script.pl line 11.
Use of each() on hash after insertion without resetting hash iterator results in undefined behavior at script.pl line 11.
Use of each() on hash after insertion without resetting hash iterator results in undefined behavior at script.pl line 11.
Use of each() on hash after insertion without resetting hash iterator results in undefined behavior at script.pl line 11.
b - 20
bb - 20
bbbb - 20
asdf - Hello
$VAR1 = {
          'asdfasdf' => 'Hello',
          'bbbbbbbb' => 20,
          'a' => 1
        };

each devolvió un par de valores de hash, y luego cambiamos el hash. Se produce la siguiente iteración del bucle y eachdevuelve un par de modificado de hash y se puede devolver la pareja, que acaba de ser añadido.

Así que si durante un recorrido de hash es necesario cambiar, entonces deberá utilizar foreach y keys. Cuando se utiliza while y each , el programa no funcionará correctamente.

Temas relacionados

Otros articulos