【问题标题】:Why does an empty Perl hash have one key?为什么一个空的 Perl 哈希只有一个键?
【发布时间】:2011-08-03 17:57:03
【问题描述】:

“如何在 Perl 中找出散列的大小?”的标准 googleable 答案是“取keys(%hash)的大小”:

my %h = {};
print scalar (keys (%h));

这会打印“1”。我期待零。另一方面。同样,

my %h = {};
$h{"a"} = "b";
$h{"x"} = "y";
print scalar keys (%h);
print "\nKey: $_" for (keys %h);

打印:

3

键:a

键:x

密钥:HASH(0x229e8)

这些额外的价值从何而来?

【问题讨论】:

  • 您应该认真考虑启用warnings pragma。它会发现这个错误。
  • 将这些行放在 ALL 脚本的顶部:use strict;使用警告;

标签: perl hash size key


【解决方案1】:
$ perl -Mwarnings -e'my %h = {}'
Reference found where even-sized list expected at -e line 1.

strictwarnings 包含在 Perl 中是有充分理由的。没有理由不使用它们。

更好的是,也可以添加diagnostics

$ perl -Mwarnings -Mdiagnostics -e'my %h = {}'
Reference found where even-sized list expected at -e line 1 (#1)
    (W misc) You gave a single reference where Perl was expecting a list
    with an even number of elements (for assignment to a hash). This usually
    means that you used the anon hash constructor when you meant to use
    parens. In any case, a hash requires key/value pairs.

        %hash = { one => 1, two => 2, };    # WRONG
        %hash = [ qw/ an anon array / ];    # WRONG
        %hash = ( one => 1, two => 2, );    # right
        %hash = qw( one 1 two 2 );      # also fine

【讨论】:

  • 我总是使用 strict,虽然我不知道“警告”和“诊断”是额外的。谢谢!
  • 'diagnostics' 仅用于调试。当程序投入生产时将其删除。
  • 使用 splain 命令行实用程序来解释 perl 错误消息。
【解决方案2】:

这以前也咬过我。

my %h = ();

注意使用() 而不是{}

解释:值{} 是一个散列的引用,而不是散列本身。在 Perl 中,引用是一种标量值,对%h 的赋值有分配单个标量值的特殊处理。它将标量字符串化(在您的情况下为您提供字符串 HASH(0x229e8)),并将该键与值 undef 相关联。

当使用() 时,从列表到哈希的分配会根据列表中的对创建键/值对,并且由于() 为空,因此哈希%h 为空。

【讨论】:

  • 没错。在第二个示例中,%h={} 将创建一个映射 {} => UNDEF 的条目。
  • 不过,这并不能解释这种情况。
  • @Tomalak - 确实如此。阅读您上面的评论。
  • 关于被咬,无论如何都没有理由用= ();声明。 my %h; 打字更少,更不容易出错。
  • 分配一个元素列表一点也不特别;这种说法使总体答案具有误导性。
【解决方案3】:

{} 是对匿名哈希的引用。所以my %h = {} 相当于我的%h = ({} => undef)

Perl 要求哈希键是字符串,因此当您使用引用作为键时,Perl 使用引用的字符串表示 (HASH(0x229e8))。

【讨论】:

    【解决方案4】:
    use Data::Dumper;
    
    my %h = {};
    warn Dumper \%h;
    

    %h 以哈希引用作为键,undef 作为值。

    输出:

    $VAR1 = {
              'HASH(0x8683830)' => undef
            };
    

    正如rafl 建议的那样,warnings 编译指示会捕捉到这一点。 查看Greg Hewgillanswer 以获取更正后的代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-01
      • 1970-01-01
      相关资源
      最近更新 更多