4

我有一个声明如下的数组哈希:

my %hash;
push @{ $hash{ $value1[$_] } }, [ $value1[$_], $value2[$_], $value3[$_], $value4[$_], $value5[$_] ] for 0 .. $#value1;

我希望能够使用以下方法检查每个键的值:

open KEYS, '>keys.txt' or die "Can't write to 'keys.txt'\n";

for my $key ( sort keys %hash ) {
    print KEYS "Key: $key contains the values: ";
    for my $value ( @{$hash{$value1}} ) {
        print KEYS "$value ";
    }   
    print KEYS "\n";
}
close(KEYS);

虽然我可以使用 Data::Dumper 可视化键和关联的值,但上述代码的输出给出了每个键的内存位置,而不是值。例如:

Key: 'Value1' contains the values: ARRAY(0x7fcd8645ba68) 

即使我将相同数量的值推送到每个数组上,每个键都包含不同数量的值

我这样做的方式有问题吗?

4

2 回答 2

6

首先,在你的内部循环中,你有

for my $value ( @{$hash{$value1}} ) {
    print KEYS "$value ";
}   

到底是$value1什么?我想你想使用$key. 总是use strict; use warnings会收到有关未定义值和未声明变量的警告。

接下来,让我们看看当我们这样做时会发生什么

my %hash;
push @{ $hash{ $value1[$_] } }, "(value$_)" for 0 .. $#value1;

相反,即我们只是将一个字符串推送到哈希中的 arrayref 上。然后,输出看起来有点像

Key: Value1 contains the values: (value0)
Key: Value2 contains the values: (value1)
Key: Value3 contains the values: (value2)

啊哈!无论我们推到该 arrayref 上的什么,都会按原样打印出来。如果你推送一个匿名 arrayref [...],你会得到那个引用的字符串化:ARRAY(0x1234567)

您可能想要该 arrayref 的内容。简单:只需取消引用它。

...;
print KEYS "[@$value] ";

或类似的东西。这里"[...]"使用的只是对输出进行可视化分组。


风格说明:

open请考虑带有词法文件句柄的 3-arg :

my $filename = "keys.txt";
open my $keys, "<", $filename or die "Can't open $filename: $!";

或使用自动错误处理:

use autodie;
open my $keys, "<", "keys.txt";

无论哪种方式,在错误消息中包含失败的原因通常很重要$!,否则几乎没有用。

根据您的喜好,您的代码可能会使用mapand来更优雅,而不是使用循环。join我可能会把循环写成

use feature 'say';
for my $key ( sort keys %hash ) {
    say {$keys} "Key: $key contains the values: "
      . join " ", map { "[@$_]" } @{ $hash{$key} };
}
于 2013-06-27T11:59:42.790 回答
3

那是因为您推送的是 arrayref 而不是值列表。

比较

push @array, [ $foo ];

push @array, $foo;

两个@arrays 都包含一个元素,但前者包含一个包含 的 arrayref $foo,而后者只包含$foo

如果你在第一个push参数之后丢失了方括号,你会很高兴。

于 2013-06-27T11:59:29.437 回答