如何在Perl中检查哈希是否为空

63

我使用下面的代码来检查哈希是否为空。是否有更好的方法并且这种方法使用安全吗?

if (!keys %hash) { print "Empty";} 
4个回答

105
if (%hash)

完全可以工作。

根据perldoc perldata:

如果你在标量上下文中评估哈希表,当哈希表为空时,它返回 false。如果有任何键/值对,则返回 true;更精确地说,返回一个字符串,该字符串由已使用的桶数和分配的桶数组成,用斜线分隔。


4
它似乎比keys %hash要慢得多。 - choroba
1
好的答案:我所缺少的是定义语义的参考文献(它不在perlop中)。 - U. Windl
@choroba,你是否也有它的解释和数字(Perl版本)? - U. Windl
@U.Windl:最近已经有所改变,因此在当前的Perl版本中,标量上下文中的%hash等同于keys%hash - choroba
似乎[!%h]在5.26中进行了更多的优化(https://perldoc.perl.org/perl5260delta#Performance-Enhancements)。[`scalar keys`]在5.28中的性能得到了改善(https://github.com/Perl/perl5/commit/6f2dc9a6b978e866e22c46235932d018da8262ba)。 - Schwern

28

曾经有一个错误导致标量上下文中被绑定的哈希总是返回false。该错误已在5.8.5版本中修复。如果您担心向后兼容性,建议使用if( !keys %hash )。否则,可以使用其他人推荐的if( !%hash )


因为有点多疑,所以我使用了scalar keys %hash == 0作为测试。所以!keys ...基本上是在对一个数组进行测试,而不是对一个哈希表进行测试。 - U. Windl
@U.Windl 是的,keys %hash 返回一个数组。scalar keys %hash 返回一个整数。请注意,Perl 函数是上下文感知的,并且可以进行优化。!%hash 被优化为返回一个布尔值。它不会遍历其键,它已经有一个计数。这段代码很可怕,但是这里有优化i = HvUSEDKEYS(hv); - Schwern

22

更简单:

if (!%hash) { 
    print "Empty";
} 
! 强制标量上下文,而在标量上下文中求值得到的哈希返回:
- 如果没有键,则返回false(虽然未在文档中定义,但实验结果返回 0) - 根据Perl的版本,可能是以下之一: - 表示使用/分配桶的数量,用于有>0个键的情况,这当然不会是false(例如,“3/6”)。(非空字符串求值为true) - 哈希中键的数量(如perldata中所述:“从Perl 5.25开始,返回值已更改为哈希中键的计数。如果您需要访问旧的行为,可以使用“Hash::Util::bucket_ratio()”代替。”)

不,它不会返回“false”,这将是一个真值。它返回零。 - Borodin

2
“更好”的定义是主观的。然而,我认为易于理解的代码可以被描述为“更好”。因此,我得出结论:!keys %hash 更好,因为编写 Perl 代码的每个人都知道这段代码的作用和工作原理。而!%hash至少对于我来说,需要查阅资料才能确保它是否真正有效或只是看起来有效。(原因是在标量上下文中哈希的返回值相当令人困惑,而数组在标量上下文中的行为是众所周知并经常使用的。)
此外,!keys %hash 是安全的。
所以,没有更好或更安全的方法来检查哈希是否为空。

1
我同意:虽然考虑使用 if (%hash) 可能会起作用,但我试图找到语义规范。可能令人困惑的是 if (@array) 似乎定义得更清楚,但出于对称性,它应该也适用于哈希表。也许这就是为什么他们最近改变了它的原因。 - U. Windl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接