【问题标题】:mysterious key come out of no where in Perl 5.14 hash tablePerl 5.14 哈希表中的神秘密钥无处不在
【发布时间】:2013-03-04 18:36:23
【问题描述】:

我在我的代码中使用哈希表

my %stat = ();
# read files and do some initialization 
# like  $stat{$key} = {k1=>v1, k2=>v2, k3=>v3};
#   I have located the buggy code
# I want to do something according to c1 and c2 parsed from each line of the file
if(!exists $stat{c1}) {   # I thought I would have initialized all possible used keys here, but it is not true as seen below
    $stat{c1} = {k1=>0, k2=>0, k3=>0};
} 
if( $c1 == $c2) {
    $stat{c1}{k1}++;
} else {
    $stat{c1}{k2}++;
    $stat{c2}{k3}++;  #Note: I forgot to check whether $stat{c2} has been initialized here!
}



map {
    my $val = $stat{$_}{k1};  
    print "$val\n";     # run time error shows "use of uninitalized $val"
} keys %stat;

我写了一些打印语句来调试程序。我发现哈希表“%stat”中神秘地出现了一些键值,尽管我从未插入过它!假设 $stat{510} 以某种方式存在,尽管我从未插入它,但它的值(在我的例子中是哈希表引用)没有初始化。我必须写一个声明:

map { delete $stat{$_} if(!defined $stat{$_}{k1}) } keys %stat;

删除不需要的键。

你能告诉我为什么会从(keys %stat)中出现一些神秘的钥匙吗?

谢谢, 杰夫

【问题讨论】:

  • 它被称为“自动生存”。
  • if (c1 == c2) ?这看起来很不对劲。错字应该是$c1$c2?
  • 是的。感谢您的指正。

标签: perl hash autovivification


【解决方案1】:

你能告诉我为什么会从(keys %stat)中出现一些神秘的钥匙吗?

因为您没有显示的代码以某种方式创建了它们。

也许你做了$stat{510}{k1}?请记住

$stat{510}{k1}

简称

$stat{510}->{k1}

$x->{...}

( $x //= {} )->{...}

所以

$stat{510}{k1}

( $stat{510} //= {} )->{k1}

注意这是如何分配给$stat{510}的?


不赞成将map 用作for 循环。

map { delete $stat{$_} if(!defined $stat{$_}{k1}) } keys %stat;

最好写成

delete $stat{$_} for grep !defined($stat{$_}{k1}), keys %stat;

甚至

delete @stat{ grep !defined($stat{$_}{k1}), keys %stat };

【讨论】:

  • @Fashandge,如果您决定将违规代码添加到您的问题中,请告诉我。我可以建议几种方法来避免首先创建哈希元素。
  • 非常感谢您的建议!实际上,我以某种方式提到了 $stat{510}{k2},而没有先初始化 $stat{510} = {k1=0, k2=0, k3=0}。
  • 我已编辑问题以添加错误代码。如果你有兴趣,请看看它,并首先给我一个关于如何避免此类错误的建议,虽然这似乎只是因为我的粗心。
  • @Fashandge,我打算建议使用no autovivification;,但那是不可能的。目前尚不清楚您希望发生什么,但既然您谈到了初始化,您可能只需要$stat{c2} //= ...;
  • 是的。使用 ( $stat{c2} //= {k1=>0, k2=>0, k3=>0} )->{k3}++ 似乎很好,而不是使用 if(!exists $stat{c2 }) ....,如果我只是在一行代码中引用 $stat{c2}。谢谢。
【解决方案2】:

因为自动复活。这意味着当您引用哈希条目时,它会毫无怨言地创建。并且如果你当时没有赋值,它会被初始化为undefined的值。因此,在您拥有的代码部分中

##read files and do some initialization 

确保您没有读取或写入带有密钥 510 的条目。

【讨论】:

    猜你喜欢
    • 2013-11-29
    • 2014-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-01
    • 1970-01-01
    相关资源
    最近更新 更多