Perl de hash na скалярном contexto

Às vezes, quando se trabalha com hashes você pode ver algum estranho frações.

Aqui está um exemplo de programa:

#!/usr/bin/perl

my %h = (
    a => 1,
    b => 2,
);

print "hash: " . %h;

Se você executar este programa em versão de Perl 5.22, então a saída deste programa será o texto hash: 2/8.

O que é essa fração?

Quando usar o operador ponto de hash utilizado em скалярном contexto. print "hash: " . %h; é a mesma coisa que print "hash: " . scalar(%h);

Linha 2/8 é o resultado de trabalho de expressão scalar(%h).

Linha 2/8 fala sobre o dispositivo interno de hash. É uma estatística de uso бакетов. Isso é completamente interna da cozinha, que muito raramente é necessário. Dentro de hash аллоцируются seções especiais sob o nome de бакеты, no qual os dados são armazenados. O que é escrito, à direita da fração é o número de аллоцированных бакетов. O número à esquerda da fração é o número de realmente utilizados бакетов. Quando você adiciona de pares de valores de hash, em algum momento, o número de аллоцированных бакетов aumenta, a fim de hash trabalhou de forma eficiente.

Aqui está um exemplo de um programa que mostra como varia esses números quando você adiciona valores de hash:

#!/usr/bin/perl

use feature qw(say);

my %h;

foreach my $i (1 .. 17) {
    $h{$i} = $i;
    say "$i - " . scalar(%h);
}

Aqui está a saída deste programa (tenha em atenção que não a cada vez que você adiciona um valor de hash aumenta o número utilizados бакетов):

1 - 1/8
2 - 2/8
3 - 3/8
4 - 3/8
5 - 4/8
6 - 4/8
7 - 4/8
8 - 5/16
9 - 5/16
10 - 6/16
11 - 6/16
12 - 6/16
13 - 6/16
14 - 7/16
15 - 8/16
16 - 12/32
17 - 12/32

Interessante que esses números não são estáveis. Se executar este script Perl, então a saída será um pouco diferente.

A mudança de trabalho a partir de Perl 5.26

As estatísticas internas hash precisa exclusivamente de classes.. Portanto, desde a versão Perl 5.26 comportamento de hash em скалярном contexto foi alterado. Agora o hash em скалярном contexto devolve um número — o número de pares de elementos em хеше. E, francamente, é isso que todos esperam obter ao se referir ao хешу em скалярном contexto.

A versão do Perl 5.26 para obter o número de pares de elementos em хеше você tinha que escrever scalar(keys(%h));. A partir da versão Perl 5.26 agora, este mesmo número pode ser obtido utilizando o scalar(%h);.

Mas se alguém precisa de obter exatamente a fração de estatísticas de хешу, é possível fazer a a função bucket_ratio a partir de uma biblioteca Hash::Util. Aqui está um exemplo de um programa em uma versão do Perl 5.26 exibe o texto hash: 2/8.

#!/usr/bin/perl

use Hash::Util qw(bucket_ratio);

my %h = (
    a => 1,
    b => 2,
);

print "hash: " . bucket_ratio(%h);

Estatísticas de хешу

Se assim você precisa entender o que está acontecendo com хешом, então você pode usar outras ferramentas. A partir da versão Perl 5.22 na biblioteca Hash::Util tem um recurso de bucket_stats_formatted, aqui está um exemplo de a sua utilização:

#!/usr/bin/perl

use Hash::Util qw(bucket_stats_formatted);

my %h = (
    a => 1,
    b => 2,
);

print bucket_stats_formatted(\%h);

A saída deste programa:

Keys: 2 Buckets: 2/8 Quality-Score: 0.94 (Good)
Utilized Buckets: 25.00% Optimal: 25.00% Keys In Collision: 0.00%
Chain Length - mean: 1.00 stddev: 0.00
Buckets              8 [00000011]
Len   0  75.00%      6 [######]
Len   1  25.00%      2 [##]
Keys                 2 [11]
Pos   1 100.00%      2 [##]

Outros artigos