我在代码中使用哈希表
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;
我写了一些print语句来调试程序。我发现一些关键值神秘地出现在哈希表“%stat”中,尽管我从未插入它!假设$ stat {510}以某种方式存在,尽管我从未插入它,但它的值(我的情况下的哈希表引用)未初始化。我必须写一个声明:
map { delete $stat{$_} if(!defined $stat{$_}{k1}) } keys %stat;
删除不需要的密钥。
你能告诉我为什么会出现一些神秘的钥匙(键%stat)?
谢谢, 杰夫
答案 0 :(得分:9)
你能告诉我为什么会出现一些神秘的钥匙(键%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 };
答案 1 :(得分:2)
因为自动化。这意味着当您引用哈希条目时,它会在没有投诉的情况下创建。如果您此时未指定值,则会使用值undefined
对其进行初始化。所以在您的代码中有
##read files and do some initialization
确保您没有使用键510
读取或写入条目。