请考虑以下代码段:
use strict;
use warnings;
my %a = ( a => 1,
b => 2,
c => 'cucu',
d => undef,
r => 1,
br => 2,
cr => 'cucu',
dr => '321312321',
);
my $c = %a;
print $c;
结果是5/8
,我不明白这代表什么。我在某处读到了这个 fraction 查找结果中的数字可能代表散列中的桶数,但显然不是这种情况。
有谁知道如何在标量上下文中评估perl哈希值?
修改
我添加了一些其他的哈希值来打印:
use strict;
use warnings;
use 5.010;
my %a = ( a => 1,
b => 2,
c => 'cucu',
d => undef,
r => 1,
br => 2,
cr => 'cucu',
dr => '321312321',
);
my $c = %a;
say $c; # 5/8
%a = ( a => 1,
b => 21,
c => 'cucu',
br => 2,
cr => 'cucu',
dr => '321312321',
);
$c = %a;
say $c; # 4/8
%a = ( a => 1,
b => 2,
c => 'cucu',
d => undef,
r => 1,
br => 2,
cr => 'cucu',
dr => '321312321',
drr => '32131232122',
);
$c = %a;
say $c; #6/8
那么,你在哈希中调用像a => 1
桶这样的'元组'?在这种情况下,为什么最后一个哈希在有9'元组'时仍然有8分母?
直到现在,谢谢大家的答复:)
答案 0 :(得分:23)
哈希是链表的数组。散列函数将密钥转换为一个数字,该数字用作存储值的数组元素(“bucket”)的索引。链表处理多个键散列到同一索引(“碰撞”)的情况。
分数的分母是桶的总数。
分数的分子是具有一个或多个元素的桶的数量。
对于具有相同元素数量的哈希值,数字越大越好。返回6/8的碰撞比返回4/8的碰撞少。
答案 1 :(得分:8)
如果在标量上下文中计算哈希值,则在哈希值时返回false 是空的。如果有任何键/值对,则返回true;更多 确切地说,返回的值是一个由数字组成的字符串 用桶和分配的桶数,用a分隔 斜线。
在您的情况下,您有五个值(1
,2
,''cucu'
,undef
和'321312321'
)已被映射到八个密钥(a
,b
,c
,d
,r
,br
,cr
和dr
)。
答案 2 :(得分:2)
使用过的桶的数量大约是键的数量;分配的桶一直是2的最低功率。键的数量。 5个键将返回5/8。大量的唯一键变得越来越慢,因此只有列表(1..128)的散列%h,具有64个键/值对,以某种方式获得标量值50/128。
但是,一旦哈希分配了它的桶,即使你缩小哈希值,它们仍将保持分配状态。我只用9对做了哈希%h,因此9/16标量;然后,当我重新分配%h只有一对时,它的标量值是1/16。
这实际上是有意义的,因为它可以让你测试哈希的大小,就像一个简单数组的标量一样。
答案 3 :(得分:1)
过分关注这个小数模式(作为散列内部细节的指标),可能会令人困惑。标量值的一个方面是&#34;标量值&#34;对于可能每个Perl程序都很重要的哈希值,也就是说,如果在 布尔上下文 中将其视为 true ,请参阅示例:< / p>
if (%h) {
print "Entries in hash:\n";
for my $k (sort keys %h) {
print "$k: $h{$k}\n";
}
}
在perldoc perldata, section Scalar-values中,您可以阅读
[...]布尔上下文只是一种特殊的标量上下文,不会转换为字符串或数字。
以及之后的某些段落
如果在标量上下文中计算哈希值,则在哈希值时返回false 是空的。如果有任何键/值对,则返回true [...]
答案 4 :(得分:1)
自Perl 5.25起,行为已更改。参见perldata for Perl 5.26:
在Perl 5.25之前,返回的值是一个字符串,其中包含 已用存储桶数和已分配存储桶数,以 斜线。这仅在确定Perl是否 内部哈希算法在数据集上的效果不佳。对于 例如,您将10,000个东西粘贴在一个哈希中,但在其中评估
%HASH
标量上下文显示1/16
,这意味着十六分之一中的一个 桶已被触及,大概包含您所有的10,000 项目。这不应该发生。从Perl 5.25开始,返回值已更改为 哈希。如果您需要访问旧的行为,可以使用 改为
Hash::Util::bucket_ratio()
。