我正在编写一个脚本来解析文件并希望将整个结果保存在一个数组中。我遇到了一个问题,我将其归结为以下代码:
use strict;
use warnings;
use Data::Dumper;
my @sections = ();
my @sections1 = qw/sect1 sect2 sect3/;
my @sections2 = qw/sect4 sect5/;
my @textbooks = ();
my $text1 = { title => "title1", author => "author1" };
my $text2 = { title => "title2", author => "author2" };
for ( @sections1 ) {
push(@sections, $_);
}
$text1->{sections} = \@sections;
@sections = ();
for ( @sections2 ) {
push(@sections, $_);
}
push(@textbooks, $text1);
$text2->{sections} = \@sections;
print Dumper($text2);
push(@textbooks, $text2);
print Dumper(@textbooks);
第一次打印Dumper的结果如下:
$VAR1 = {
'title' => 'title2',
'sections' => [
'sect4',
'sect5'
],
'author' => 'author2'
}
第二个结果是:
$VAR1 = {
'sections' => [
'sect4',
'sect5'
],
'title' => 'title1',
'author' => 'author1'
};
$VAR2 = {
'title' => 'title2',
'sections' => $VAR1->{'sections'},
'author' => 'author2'
};
我对此有两个问题,我确信它们是相关的。
我意识到第一部分是引用,因此它们包含我期望第二部分的内容。我认为
@sections=()
行会创建一个新数组,并且稍后会创建一个新引用。显然我的想法不正确。第二部分发生了什么?从
$text2
的输出来看,在推送之前它看起来是正确的。
最佳答案
你完全正确:
@sections = ();
不创建一个新数组,它会覆盖旧数组的内容。
Data::Dumper
“隐藏”的内容之一是引用。
试试这个:
foreach my $key ( keys %{$text2} ) {
print $key, $text2 -> {$key},"\n"
}
还有:
foreach my $thing (@textbooks) {
print "TB ref $thing\n";
foreach my $key ( keys %{$thing} ) {
print "$key => ", $thing->{$key}, "\n";
}
}
从后者中,你会得到类似的结果:
TB ref HASH(0x12de994)
sections => ARRAY(0x12e43b4)
author => author1
title => title1
TB ref HASH(0x12de9ac)
sections => ARRAY(0x12e43b4)
title => title2
author => author2
请注意这里的数组如何具有相同的 ID - 这是问题的根源。您的哈希有两次相同的引用。 (哈希数组中的父哈希
不同)
一个简单的解决方法可能是从使用 @sections
切换到 $sections
,因为 while:
@sections = ();
不创建"new"数据结构:
$sections = [];
因为[]
是一个匿名数组,所以您正在创建,并且只是重新分配引用。
另一个解决方案是通常使用 my
缩小范围,但您的代码效果不太好 - 不过与 foreach
循环配合得很好。
关于arrays - 将 Perl 数组放入哈希中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30666405/