我想创建10个一维数组,并将这10个一维数组放到另一个一维数组中,并将一些数据存储到某个特定的数组索引中。
但是我期望的输出应该是
expect output real output
0 1
1 1
0 1
3 1
0 1
5 1
0 1
7 1
0 1
0 1
这是我的代码
@Hits = ();
# Create 10 one dimension array
for($i=0;$i<=9;$i++)
{
@Space = ();
push(@Hits,\@Space);
}
# Store some data to some index
push(@{$Hits[1]},1);
push(@{$Hits[3]},3);
push(@{$Hits[5]},5);
push(@{$Hits[7]},7);
# print the first element of 10 arrays
for($i=0;$i<=9;$i++)
{
print $Hits[$i]->[0];
print "\n";
}
感谢
答案 0 :(得分:6)
问题是你没有正确地声明你的变量。对于每个脚本,你应该
use strict; use warnings;
这不允许常见错误来源,警告iffy stuff,并强制您正确声明所有变量。
默认情况下,所有未声明的变量都被视为全局。因此,在
for($i=0;$i<=9;$i++)
{
@Space = ();
push(@Hits,\@Space);
}
@Space
在每次迭代中引用相同的数组。因此,@Hits
中的所有十个条目都是对同一个数组的引用。让我们检查@Hits
实际上是什么。我们可以使用Data::Dumper
或Data::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
时,我们都会获得 new @Space
。哦,我使用了foreach循环,它使用(词法)0 .. 9
变量遍历范围$i
。我发现这比你使用的C风格循环更容易理解。
因为@Hits
中的每个元素现在都是不同的 arrayref,所以我们得到了预期的数据结构。正如Data::Dump
输出:
[[], [1], [], [3], [], [5], [], [7], [], []]
当我们现在执行你的循环打印出每个子数组的第一个值时,你可能会对数字之间的空行感到惊讶。这是因为例如第一个arrayref在索引0
没有条目,因此返回特殊的undef
值。当用作字符串时,这是空字符串。如果您遵循我的建议并执行use warnings
,您还会收到一条消息,指出您正在打印未初始化的值。
我们可以通过测试定义来解决这个问题,否则提供零。从perl5 v10开始,我们可以使用defined-或operator //
(在早期的perls上,||
逻辑或必须这样做。)
for my $i (0 .. 9) {
my $value = $Hits[$i][0] // 0;
print "$value\n";
}
我们可以改进其他一些内容:
@Space
数组;当您取消引用像@{ $Hits[$i] }
这样的数组条目时,Perl会在幕后执行此操作。这称为 autovivification 。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位初始化值,因此它们不会显示。我们可以通过迭代切片 @Hits[0 .. 9]
来修改它。)
答案 1 :(得分:1)
我改变你的代码如下:
#! /usr/bin/perl -w
@Hits = ();
push(@{$Hits[1]},1);
push(@{$Hits[3]},3);
push(@{$Hits[5]},5);
push(@{$Hits[7]},7);
#print the content of
for($i=0;$i<=9;$i++)
{
if (defined ($Hits[$i])) {
print "$Hits[$i][0]\n";
} else {
print "0\n";
}
}
将@space的ref赋给@Hits并且导致错误的结果是不正确的。没有必要在perl中初始化@Hits。
答案 2 :(得分:0)
perl -e "use Data::Dump; @sf=(); push @{$sf[0]},"0"; push @{$sf[1]},"1"; dd \@sf;"
[[0], [1]]
或
perl -e "use Data::Dump; @sf=(); push @sf,["0"]; push @sf,["1"]; dd \@sf;"
[[0], [1]]