如果其他地方已经解决了,请道歉。我搜查了一下。
我正在使用一个配置文件,通过左对齐每个块的名称和缩进每个名称的参数来分隔数据块(请参阅下面的__DATA__
)。我编写了一个脚本,将每个块存储到散列中,其中$hash{name}
键指向标量值,%hash{args}
键指向值数组。由于每个块都存储在自己的哈希中,因此对哈希的引用将匿名存储在数组中。最后我想逐个抓取这些哈希并处理它们中的值,但是我在迭代数组时遇到了麻烦。
当我尝试打印存储在每个哈希中的值时,它似乎是在列表上下文中的那个数组中使用哈希引用,所以如果%hash {args}是对具有三个元素的数组的引用,则再多三次foreach循环运行。
如何让该循环中的代码只为我已经插入该数组的每个哈希引用运行一次?
如果你检查我的输出,很明显嵌套数组引用需要被解除引用但我仍然坚持正确的循环,我还没有解决。也许解决方案会解决这两个问题?
看哪:
use strict;
use warnings;
my @array;
my %hash;
my ($name, $args);
while (my $line = <DATA>) {
chomp($line);
if ($line !~ /^\s/)
{
my ($key) = $line =~ /^\S+/g;
$hash{name} = $key;
print "Defined a name $key\n";
}
else
{
$line =~ s/^\s+//;
push (@{ $hash{args} }, $line);
print "Defined an arg $line\n";
}
push (@array, \%hash);
}
foreach my $i (@array)
{
foreach my $h (keys %{$i})
{
print $h . "\t";
print $i->{$h} . "\n";
}
}
__DATA__
Sports
Basketball
Tennis
Boxing
Guys
Tom
Dick
Harry
这是输出:
Defined a name Sports
Defined an arg Basketball
Defined an arg Tennis
Defined an arg Boxing
Defined a name Guys
Defined an arg Tom
Defined an arg Dick
Defined an arg Harry
args ARRAY(0x4a8e24)
name Guys
args ARRAY(0x4a8e24)
name Guys
args ARRAY(0x4a8e24)
name Guys
args ARRAY(0x4a8e24)
name Guys
args ARRAY(0x4a8e24)
name Guys
args ARRAY(0x4a8e24)
name Guys
args ARRAY(0x4a8e24)
name Guys
args ARRAY(0x4a8e24)
name Guys
答案 0 :(得分:1)
在建立数据结构时,你犯了一些错误:
$key
分配给同一个$hash{name}
字段。以前的内容被覆盖。最后一个值Guys
保持不变。%hash
的引用推送到@array
。因为引用反映了原始对象的所有更改,所以每次都会得到相同的输出。使用不同的数据结构; - )
您的数据的工作方式如下:我们有一个名称,每个名称都带有值列表。集合在Perl中使用哈希建模,因此我们使用一个:
my %hash = ();
每个条目都包含对包含值的数组的引用。最终的数据结构如下所示:
%hash = (
Sports => ["Basketball", "Tennis", "Boxing"],
Guys => ["Tom", "Dick", "Harry"]
);
您可以使用Data::Dumper
模块检查当前的数据结构:
use Data::Dumper;
print Dumper (\%name); # has to be given references
要使用此数据结构,只需对代码进行最小程度的改进:
my %hash;
my $key;
while (my $line = <DATA>) {
chomp $line;
if ($line =~ /^(\S+)/) {
$key = $1;
$hash{$key} = []; # this is the main difference
print "Defined a name $key\n";
} else {
$line =~ s/^\s+//;
push @{ $hash{$key} }, $line;
print "Defined an arg $line\n";
}
}
我也改变了编码风格,但基本上唯一的区别是我使用名称作为哈希键。我记得在循环外使用的最后一个$key
,以便所有参数都知道要去哪里。
当我想打印出数据结构时,如果名称顺序不重要,我会使用each
函数:
while (my ($name, $arrayRef) = each %hash) {
my @args = @$arrayRef; # dereference the array
print qq{name $name with args "@args"\n};
}
或
while (my ($name, $arrayRef) = each %hash) {
print "name\t$name\n";
print "arg\t$_\n" foreach @$arrayRef;
}
答案 1 :(得分:1)
我认为你需要一个不同的数据结构。试试这个:
use strict;
use warnings;
use Data::Dumper;
my @array;
my %hash;
my ( $name, $args, $key );
while ( my $line = <DATA> ) {
chomp($line);
if ( $line !~ /^\s/ ) {
$key = $line; #=~ /^\S+/g;
print "Defined a name $key\n";
}
else {
$line =~ s/^\s+//;
push (@{$hash{$key}}, $line);
print "Defined an arg $line\n";
}
}
print Dumper(\%hash);
__DATA__
Sports
Basketball
Tennis
Boxing
Guys
Tom
Dick
Harry
<强>输出:强>
$VAR1 = {
'Sports' => [
'Basketball',
'Tennis',
'Boxing'
],
'Guys' => [
'Tom',
'Dick',
'Harry'
]
};
我试图让解决方案接近您自己的代码。
编辑:如果处理多级数据结构,总是使用Data::Dumper
来转储数组/哈希中的确切内容。这将帮助您解决分配问题,例如此实例。
您的数据结构如下所示:
$VAR1 = [
{
'args' => [
'Basketball',
'Tennis',
'Boxing',
'Tom',
'Dick',
'Harry'
],
'name' => 'Guys'
},
$VAR1->[0],
$VAR1->[0],
$VAR1->[0],
$VAR1->[0],
$VAR1->[0],
$VAR1->[0],
$VAR1->[0]
];