Perl hash w kontekście скалярном

Czasami podczas pracy z хешами można zobaczyć jakieś dziwne ułamki.

Oto przykład programu:

#!/usr/bin/perl

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

print "hash: " . %h;

Jeśli uruchomić ten program w wersji Perl 5.22, to wniosek ten program będzie tekst hash: 2/8.

Co to za ułamek?

Przy użyciu operatora punkt mieszania jest stosowany w скалярном kontekście. print "hash: " . %h; to to samo, co print "hash: " . scalar(%h);

Wiersz 2/8 — to wynik pracy wyrażenia scalar(%h).

Wiersz 2/8 mówi o wewnętrzne urządzenie mieszania. To statystyki użytkowania бакетов. To zupełnie wewnętrzna kuchnia, która jest bardzo rzadko potrzebna. Wewnątrz mieszania аллоцируются specjalne działy pod nazwą бакеты, w których są przechowywane dane. To co jest napisane po prawej stronie od ułamka jest liczba аллоцированных бакетов. Liczba po lewej stronie od ułamka jest liczba faktycznie używanych бакетов. Po dodaniu par wartości hash w pewnym momencie ilość аллоцированных бакетов wzrasta, aby hash pracował skutecznie.

Oto przykład programu, który pokazuje jak zmienia się te liczby po dodaniu wartości hash:

#!/usr/bin/perl

use feature qw(say);

my %h;

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

Oto wniosek z tego programu (należy pamiętać, że nie za każdym razem przy dodawaniu wartości hash wzrasta liczba używanych бакетов):

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

Ciekawe, że liczby te są nietrwałe. Jeśli kilka razy uruchamiać ten skrypt Perla, to wniosek będzie się nieco różnić.

Zmiana pracy od Perl 5.26

Wewnętrzne statystyki mieszania potrzebuje wyjątkowo rzadko. Dlatego począwszy od wersji Perl 5.26 zachowanie mieszania w скалярном kontekście została zmieniona. Teraz hash w скалярном kontekście zwraca liczbę — ilość par elementów w хеше. I, szczerze mówiąc, właśnie to wszystko i oczekują uzyskać zwracając się do хешу w скалярном kontekście.

Do wersji Perl 5.26 aby uzyskać liczbę par elementów w хеше trzeba było napisać scalar(keys(%h));. Począwszy od wersji Perl 5.26 teraz to ten sam numer można uzyskać za pomocą scalar(%h);.

Ale jeśli ktoś chce uzyskać dokładnie śrut ze statystykami na хешу, to może to zrobić za pomocą funkcje bucket_ratio z biblioteki Hash::Util. Oto przykład programu, który w wersji Perl 5.26 wyświetla tekst hash: 2/8.

#!/usr/bin/perl

use Hash::Util qw(bucket_ratio);

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

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

Dodatkowe statystyki хешу

Jeśli wszystkie tak trzeba zrozumieć, co się dzieje z хешом, to można użyć innych narzędzi. Począwszy od wersji Perl 5.22 w bibliotece Hash::Util pojawiła się funkcja bucket_stats_formatted, oto przykład jej użycia:

#!/usr/bin/perl

use Hash::Util qw(bucket_stats_formatted);

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

print bucket_stats_formatted(\%h);

Wniosek z tego programu:

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 [##]

Inne artykuły