问题是您没有正确声明变量。对于每个脚本,您应该
use strict; use warnings;
这不允许常见的错误源,警告不确定的东西,并强制您正确声明所有变量。
默认情况下,所有未声明的变量都被视为全局变量。因此,在
for($i=0;$i<=9;$i++)
{
@Space = ();
push(@Hits,\@Space);
}
the@Space
在每次迭代中引用相同的数组。因此,所有十个条目@Hits
都是对同一数组的引用。让我们检查一下@Hits
实际情况。我们可以使用Data::Dumper
orData::Dump
模块(后者通常产生更漂亮的输出):
use Data::Dump; # use Data::Dumper;
dd \@Hits; # print Dumper \@Hits;
我们得到Data::Dumper
(更容易理解):
$VAR1 = [
[
1,
3,
5,
7
],
$VAR1->[0],
$VAR1->[0],
$VAR1->[0],
$VAR1->[0],
$VAR1->[0],
$VAR1->[0],
$VAR1->[0],
$VAR1->[0],
$VAR1->[0]
];
所以我说解决方案是声明你的变量。具体来说,我们需要词法变量。这些变量仅在声明它们的块内可见。这使得对代码的推理变得更加容易。我们可以像这样声明一个词法变量:
my $foo = 123;
当我们有一个循环时
my @Hits;
for my $i (0 .. 9) {
my @Space;
push @Hits, \@Space;
}
然后每次my
执行时,我们都会得到一个新 @Space
的. 0 .. 9
哦,我使用了一个 foreach 循环,它使用(词法)$i
变量迭代范围。我发现这比您使用的 C 样式循环更容易理解。
因为@Hits
现在每个元素都是不同的arrayref,所以我们得到了预期的数据结构。作为Data::Dump
输出:
[[], [1], [], [3], [], [5], [], [7], [], []]
当我们现在执行打印出每个子数组的第一个值的循环时,您可能会对数字之间的空行感到惊讶。这是因为例如第一个 arrayref 在 index 处没有条目0
,因此返回特殊undef
值。当用作字符串时,这是空字符串。如果您按照我的建议执行了use warnings
,您还会收到一条消息,表明您正在打印一个未初始化的值。
我们可以通过测试定义性来解决这个问题,否则提供零。从 perl5 v10 开始,我们可以//
为此使用定义或运算符(在早期的 perls 中,||
逻辑或必须这样做)。
for my $i (0 .. 9) {
my $value = $Hits[$i][0] // 0;
print "$value\n";
}
还有一些我们可以改进的地方:
- 我们不必手动创建
@Space
数组;当您取消引用数组条目(如@{ $Hits[$i] }
. 这称为自动存活。
- 我们不仅可以遍历范围,还可以遍历数组。这比硬编码索引要好得多。
- 从 v10 开始,您可以使用该
say
功能。该say
函数完全一样print
,但在末尾附加了一个换行符。
这是我编写该代码的方式:
#!/usr/bin/perl
use strict; use warnings; use feature 'say';
my @Hits;
for my $i (1, 3, 5, 7) {
push @{ $Hits[$i] }, $i;
}
for my $arrayref (@Hits) {
say $arrayref->[0] // 0;
}
输出:
0
1
0
3
0
5
0
7
(请注意,我们从未在位置 8 和 9 处初始化值,因此未显示它们。我们可以通过迭代slice @Hits[0 .. 9]
来修改它。)