迭代哈希的Perl警告

时间:2014-09-02 20:40:52

标签: perl hash foreach warnings

以下代码通过提供此警告消息让我困惑了一段时间:Use of uninitialized value in join or string at ./mycode.pl line 666.其中第666行:print "@{n0->{$x}{$y}}\n";。请注意,n是字符串数组的哈希哈希,如下所示:

n  = (
 x0 => {
   y0 => [ "foo00", "bar00" ]
   y1 => [ "foo01", "bar01" ]
   ...
 }
 x1 => {
   y0 => [ "foo10", "bar10" ]
   y1 => [ "foo11", "bar11" ]
   ...
 }
...
)

以下是代码:

my $rn =\%n;
for my $x (keys %$rn){
    print "$x\n";
    for my $y (keys %{$rn->{$x}}){
        print "@{$rn->{$x}{$y}}\n";
    }
}

我不明白为什么Perl会抱怨uninitialized values。从本质上讲,我预计元素必须具有值,否则它们甚至不会存在,因此不会出现在迭代中。而且,输出符合我的预期。

我在这里失踪的关键是什么?我怎么能摆脱它?

2 个答案:

答案 0 :(得分:0)

以下代码有效;看看你的代码有什么不同。

use strict;
use warnings;

my %n = (
 x0 => {
   y0 => [ "foo00", "bar00" ],
   y1 => [ "foo01", "bar01" ]
 },
 x1 => {
   y0 => [ "foo10", "bar10" ],
   y1 => [ "foo11", "bar11" ]
 }
);

my $rn =\%n;
for my $x (keys %$rn){
    print "$x\n";
    for my $y (keys %{$rn->{$x}}){
        print "@{$rn->{$x}{$y}}\n";
    }
}

也许您的数据并不完全符合您的想法? 添加use Data::Dumper; print Data::Dumper->new([$rn])->Useqq(1)->Terse(1)->Dump;并查看是否有任何线索为您提供了线索。

您可以通过在打印之前放置它来跟踪特别是触发警告的值:

local $SIG{__WARN__} = sub { print "warning given when x is $x and y is $y: ", @_ };

那就是说,除非其中一个数组元素未定义,否则除非我将$"设置为undef,否则我无法发出警告(尽管您使用的是perl的古老版本和我不是,所以这可能会产生影响。)如果实际上你正在改变$"(通常是空格字符),你应该避免在字符串中插入一个数组,而是明确地做:

print join(" ", @{$rn->{$x}{$y}}), "\n";

答案 1 :(得分:0)

乍一看,您的代码似乎没有任何问题。因此,您的数据存在争议。

我建议使用Data::Dump(我的偏好)或Data::Dumper等模块来检查您的数据。然后,您可以更容易地确定哪个密钥具有错误数据,但具有哪个值。

如果你想要花哨,你甚至可以创建一个特殊的$SIG{__WARN__}处理程序,只有在发现错误时才输出附加信息。

use strict;
use warnings;

my %n = (
    x0 => {
        y0 => [ "foo00", "bar00" ],
        y1 => [ "foo01", "bar01" ],
    },
    x1 => {
        y0 => [ "foo10", undef ],
        y1 => [ "foo11", "bar11" ],
    },
);

my $rn = \%n;
for my $x ( keys %$rn ) {
    print "$x\n";
    for my $y ( keys %{ $rn->{$x} } ) {
        # Catch Warning and output additional info
        local $SIG{__WARN__} = sub {
            warn @_;   # Output regular warning info
            use Data::Dump;
            dd $x, $y, $rn->{$x}{$y};
        };

        print "@{$rn->{$x}{$y}}\n";
    }
}

输出:

x1
foo11 bar11
Use of uninitialized value in join or string at b.pl line 24.
("x1", "y0", ["foo10", undef])
foo10 
x0
foo01 bar01
foo00 bar00