Como passar por хешу em Perl

Tarefa. No código Perl do programa, há hash %h. Neste хеше há alguns pares de valores. Precisa ir a todos os elementos de hash e executar as ações de cada item.

Caminhar por хешу com o foreach

Mais frequentemente, a maneira mais conveniente para contornar o hash é usar foreach. Aqui está um exemplo 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";
}

Tudo é bastante simples. Primeiro, nós criamos o hash %h em que há três pares de valores. Mais adiante encontra-se o ciclo. Com a ajuda de keys %h temos a lista de todas as chaves de hash (neste exemplo, é a linha 'a', 'b' e 'asdf'). String com a chave é colocado na variável $key executado e o corpo do loop, então em $key é colocado na seguinte chave de hash e, novamente, o corpo do loop é executado, e assim ocorre em todas as chaves.

Se você salvar o código em um arquivo de script.pl e executá-lo perl script.pl, você verá um conjunto de pares de valores, que contém хеше:

b - 20
asdf - Hello
a - 1

O hash é desordenado conjunto de pares de valores. E a conclusão é bem visto — a ordem em que foram derivadas elementos de hash não coincidem com o fato de a ordem em que eles são definidos no código do programa. Além disso, se executar o este script várias vezes, então a ordem dos elementos na saída irá variar. keys %h retorna a lista de chaves hash em ordem aleatória. Se precisa para que a ordem foi sempre o mesmo, então para isso, por exemplo, você pode usar classificação foreach my $key (sort keys %h) {.

Passar por хешу com o while e each

Outra maneira para contornar todo o hash é usar o ciclo de while e a palavra-chave each. Aqui está o código que funciona da mesma forma do exemplo 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 retorna uma lista de dois elementos — chave de hash e do seu correspondente valor. É exatamente a mesma, como em caso de keys a ordem em que each retorna um par de valores não está definido. Diferentes execuções de uma mesma o programa irá retornar um par de diferentes ordens.

Nós atribuímos o valor que devolveu each variáveis. each lembra-se de que um par de hash ele já deu e na próxima vez que você retornar outro par de valores. Isso vai continuar até que each não retornará todos os casais, depois disso, ele irá retornar uma lista vazia. Até each retorna um par de valores é executado corpo while ciclo, uma vez que ele retorna uma lista vazia, o ciclo de whiletermina.

A mudança de valores em хеше

Quando você usa o foreach ciclo, keys %h é executado apenas uma vez. Quando você usa o whileciclo de each é executado em cada iteração.

Estender a tarefa anterior — precisamos não apenas a saída de todos os elementos de hash, mas ainda e substituí-los. Isso é completamente sem problemas, você pode fazer quando você usa o foreach e 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;

A saída do programa:

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

Mas não consigo fazer ao usar 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;

Quando você executa este programa, aparecerá algo como:

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 devolveu um par de valores de hash, e então nós mudamos de hash. Acontece a próxima iteração do ciclo e eachretorna um par modificado a partir do hash e ele pode retornar a um casal que acaba de se adicionou.

Então, se você cruzar um hash precisa mudar, precisa usar foreach e keys. Quando você usa while e each , o programa será executado corretamente.

Temas relacionados

Outros artigos