我在这里有一个关于裁判的非常noob-ish问题,但至少仍然让我感到困惑......
在下面的代码示例中,我正在尝试创建数组哈希:
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Terse = 1;
$Data::Dumper::Quotekeys = 0;
my @a1 = ( 'a1', 1, 1, 1 );
my @a2 = ( 'a2', 2, 2, 2 );
my $a1_ref = \@a1;
my $a2_ref = \@a2;
my @a = ( $a1_ref, $a2_ref );
my %h = ();
for my $i ( 1 .. 2 ) {
$h{"$i"} = \@a;
}
say Dumper \%h;
Dumper输出
{
'1' => [
[
'a1',
1,
1,
1
],
[
'a2',
2,
2,
2
]
],
'2' => $VAR1->{'1'}
}
这里的问题是:
为什么$ h {'2'}引用$ h {'1'}?我正在尝试使用由@a数组构成的相同键值创建哈希%h。我希望哈希的每个键值都基于@a拥有它自己的AoA,但我得到的引用是$ h {'1'}。我做错了什么?
我试图实现的翻车机输出是:
{
'1' => [
[
'a1',
1,
1,
1
],
[
'a2',
2,
2,
2
]
],
'2' => [
[
'a1',
1,
1,
1
],
[
'a2',
2,
2,
2
]
]
}
任何帮助表示赞赏。提前谢谢!
-Dan
答案 0 :(得分:4)
$h{'2'}
不是$h{'1'}
的引用,而是两个引用同一个数组,即@a
。你可能想要的是:
for my $i ( 1 .. 2 ) {
$h{"$i"} = $a[$i - 1];
}
相当于:
$h{'1'} = $a[0]; # i.e., $a1_ref
$h{'2'} = $a[1]; # i.e., $a2_ref
使$h{'1'}
引用@a1
,$h{'2'}
引用@a2
。
顺便说一下,您可能会发现使用符号[ ... ]
和{ ... }
创建对匿名数组和哈希(分别)的引用会很有帮助。由于除了@a1
和@a2
之外,您永远不会使用$a1_ref
和$a2_ref
,因此您也可以直接创建后者:
my $a1_ref = [ 'a1', 1, 1, 1 ]; # reference to a new array (no name needed)
my $a2_ref = [ 'a2', 2, 2, 2 ]; # ditto
编辑更新的问题:要复制数组,您可以写:
my @orig = (1, 2, 3);
my @new = @orig;
或:
my $orig_ref = [1, 2, 3];
my $new_ref = [@$orig_ref]; # arrayref -> array -> list -> array -> arrayref
在你的情况下,如果我理解正确,你需要执行一个稍微“深度”的副本:你不只是想要两个具有相同元素的数组,你想要两个数组,其元素是对不同数组的引用相同的元素。没有内置的Perl方法,但您可以编写循环,或使用map
函数:
my @orig = ([1, 2, 3], [4, 5, 6]);
my @new = map [@$_], @orig;
所以:
for my $i ( 1 .. 2 ) {
$h{"$i"} = [map [@$_], @a];
}
答案 1 :(得分:2)
这(你正在做的)将使$h{1}
和$h{2}
引用同一个数组@a
:
for my $i ( 1 .. 2 ) {
$h{"$i"} = \@a;
}
这会使$h{1}
和$h{2}
引用两个不同的对象,每个对象 @a
的副本:
for my $i ( 1 .. 2 ) {
$h{"$i"} = [ @a ];
}
但是内部数组仍然是别名。听起来你想要一个深层拷贝:
答案 2 :(得分:2)
我认为这段代码符合您的要求。
我已切换到Data::Dump
,因为我更喜欢它的输出。
引用数据的问题在于,无论复制该引用多少次,它仍然指向相同的数据,因此在引用它的任何地方都会重新选择该数据的变化。
要制作数组的第二个独立副本,您当然可以编写my @copy = @array
并从那里开始工作。但是使用[ @array ]
很方便,它将数组的内容复制到一个新的匿名数组并返回对它的引用。
您希望每个哈希值都是对双元素数组的引用,每个数组都是对包含@a1
和@a2
数据的另一个数组的引用。这段代码将为您完成。
另一点是,由于散列键是字符串,因此对它们使用数值是不常见的:它表示您应该使用数组。但由于所有这些显然都是占位符数据,所以我并不太担心。
use strict;
use warnings;
use Data::Dump;
my @a1 = qw/ a1 1 1 1 /;
my @a2 = qw/ a2 2 2 2 /;
my %h;
for my $i ( 1, 2 ) {
$h{$i} = [ [ @a1 ], [ @a2 ] ];
}
dd \%h;
<强>输出强>
{
1 => [["a1", 1, 1, 1], ["a2", 2, 2, 2]],
2 => [["a1", 1, 1, 1], ["a2", 2, 2, 2]],
}
答案 3 :(得分:0)
上面的所有答案都指出了正确的解决方案(和问题)。这需要制作一个结构的副本,然后使用它的引用。我在这里指出的数组和散列只是占位符,用于更复杂的结构。因此,为了制作结构的副本,我使用了Clone模块,该模块完全执行结构的深层复制并返回对它的不同引用。 谢谢大家的回复!