问题描述
我有一个数组和散列定义为:
my @test_array;
my %test_hash = (
line_1 => 1,line_2 => 2,line_3 => 3,);
我想将该哈希添加到数组中,然后修改哈希并将任何新版本推送到数组
push (@test_array,%test_hash);
$test_hash{line_1} = 2;
push (@test_array,%test_hash);
最后,我需要在传入数组中的每个散列时调用一个方法,一次一个:
for my $hash (@test_array) {
$self->do_thing(%$hash)
}
但是,当我打印出数组时,似乎两个散列都存储在一个元素中:
use Data::Dumper;
print Dumper (\@test_array);
### Begin Output ###
$VAR1 = [
'line_1',1,'line_3',3,'line_2',2,'line_1',2
];
我的方法调用基本上应如下所示,第二次循环时散列中包含 line_1 => 2
:
$self->do_thing(
line_1 => 1,);
有人能解释一下为什么所有这些都被添加到单个数组元素中吗?我希望 Dumper 输出将包含第一个推送的哈希值 $VAR1 和第二个推送的 $VAR2 - 但事实并非如此。
谢谢!
解决方法
您不能向数组添加散列,但可以添加对散列的引用:
push @array,\%hash;
所有引用都是标量,列表是标量的集合。数组是保存列表的变量。
而且,当您想将数据结构传递给子例程并保持其完整时(因此,不要像您在此处看到的那样列出它),请传递引用。由于子程序得到一个引用,它可以直接改变哈希值。
$self->do_thing($hash);
现在是棘手的部分。在你的问题中间,你谈论更新哈希。我想你可能想表达两件事。
-
由于您有对哈希的引用,因此您对原始哈希所做的任何更改都已对引用可见。它们指向相同的数据。
-
如果你想制作一个新的散列来添加到数组中(除了你刚刚添加的那个),你需要做更多的工作。如果你想要同一事物的不同版本,你可以克隆哈希。
Storable
与 Perl 一起提供并具有dclone
函数:
use Storable qw(dclone);
my %hash = ...;
# now you have a completely disconnected copy (deep copy)
push @array,dclone(\%hash);
# change the hash. The reference in `@array` is not affected
$hash{foo} = ...;
# add an additional deep copy clone
push @array,dclone(\%hash);
所有这些都包含在 Intermediate Perl 以及 Perl Data Structures Cookbook 等文档中。