【问题标题】:perl assigns key with undefined valueperl 为键分配未定义的值
【发布时间】:2015-11-25 06:19:22
【问题描述】:

我有一段代码曾经看起来像这样:

$deepest{$xval} = $Evalue unless exists $deepest{$xval}; 

#some code

foreach (keys %deepest){
  print $datfh $_, "\t", $deepest{$_}, "\n";
}

然后我改成

$deepest{$xval} = [$Evalue, $id] unless exists $deepest{$xval}[0];

#some more code

foreach (keys %deepest){
  print $datfh $_, "\t", $deepest{$_}[0], "\t", $deepest{$_}[1], "\n";
}

现在我得到,当我之后打印哈希时,很多警告:

Use of uninitialized value in print

这是我以前没有得到的。

为什么新的哈希结构与旧的不同?有什么办法可以避免出现未初始化的条目吗?

更新:愚蠢的我,我没有在原始问题中包含实际导致错误的代码部分。现在它进来了,现在我也知道如何摆脱它,即将exists $deepest{$xval}[0] 替换为exists $deepest{$xval},不知何故第一种方法创建了哈希条目。

【问题讨论】:

  • 您可能想用$deepest{$xval} //= [$Evalue, $id] 替换长的unless 语句。它完全相同,因为它会设置 $deepest{$xval} 的值(如果它存在但具有 undef 的值)以及它不存在,但那是几乎可以肯定适合您的目的
  • 看来%deepest 中有一个键,它的值是一个包含一个元素的数组引用。
  • @Borodin 感谢您的提示,我会记住这一点。不过,在这段代码中,除非语句包含更多条件,但我没有提出问题,因为它们没有产生问题,所以在这种情况下,无论如何我都必须使用除非。
  • 打印语句中不应该是$deepest{$_}->[0](等等)吗?哈希值是数组references,而不是数组。
  • “不知何故”与 perl 的自动激活有关 - perlmonks.org/?node_id=691557

标签: perl hashtable


【解决方案1】:

试试这个代码

#should check exists of hash, not array
$deepest{$xval} = [$Evalue, $id] unless exists $deepest{$xval};
# some code
foreach (keys %deepest){
  # its good practice to use -> for arrayrefs and hashrefs ($deepest{$_} - arrayref)
  #and you should check $deepest{$xval}->[1] ( $id ) , maybe $id is undef
  warn '$id is not defined ' unless defined $deepest{$_}->[1];
  print $datfh $_, "\t", $deepest{$_}->[0], "\t", $deepest{$_}->[1],    "\n";
}

【讨论】:

  • 这个答案确实可以对发生的事情进行更多解释,以及为什么会解决它。
  • 是的,我添加了一些 cmets
【解决方案2】:

Exists 测试一个键是否存在。这很有用,但它可能并不完全是您想要的,因为如果该键的 value 是 undef,它就可以工作。

你可能会发现 defined 会做你想做的事:

my %hash = ( key => undef ); 

print "Key exists\n" if exists $hash{$key};
print "Key defined\n" if defined $hash{$key}; 

在你的情况下:

my %hash = ( key => [ ] ); 
print "Exists\n" if exists $hash{key};
print "Defined\n" if defined $hash{key}; 
print "Is true\n" if $hash{key}; 
print "Has values\n" if @{$hash{key}};

但是看看你的代码,我的想法是——你插入的那个匿名数组——它肯定总是至少有两个(定义的)元素吗?

因为您可以解决该问题的一种明显方法是:

my %hash = ( key => [ "value", undef ] ); 
print $hash{key}[0], $hash{key}[1],"\n";

关于取消引用(因为它对于 cmets 来说有点太大了) - 实际上您只需要取消引用一次。

因为:

my $array_ref = [ 1, 4, 9 ]; 
print $array_ref,"\n"; #scalar value; 
print $array_ref -> [0],"\n"; #also scalar, from within array. 

如果你有:

my @array = ( [1, 4, 9], 
              [16, 25, 36], );
print "@array\n";
print \@array,"\n";
print $array[0],"\n"; #reference scalar - but because of the brackets
                      #perl knows you're referring to @array. 
print $array[0][1],"\n"; #scalar, but implicitly dereferenced.
print $array[0]->[1]; #dereferenced scalar, same as above.

最后两种情况是一样的——为什么?好吧,因为它必须如此。 “父”数组必须是一个引用,因为这就是数组数组的工作方式,所以perl 可以自动取消引用。

【讨论】:

    猜你喜欢
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    相关资源
    最近更新 更多