理解perl中的数据结构
我试图理解perldsc文档中的“常见错误”部分。当作者提到: 在构建类似数组的数组时,最常见的两个错误是:要么意外地计算元素的数量,要么重复引用同一内存位置。在这种情况下,只需获取计数而不是嵌套数组:理解perl中的数据结构,perl,Perl,我试图理解perldsc文档中的“常见错误”部分。当作者提到: 在构建类似数组的数组时,最常见的两个错误是:要么意外地计算元素的数量,要么重复引用同一内存位置。在这种情况下,只需获取计数而不是嵌套数组: #!/usr/bin/perl -w use strict; use Data::Dumper; my @count; my @new_array; for my $i (1..10) { #my @count; my @array = somefu
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my @count;
my @new_array;
for my $i (1..10) {
#my @count;
my @array = somefunc($i);
push @new_array, [@array];
}
sub somefunc {
my $a = shift;
return $a * $a;
}
print Dumper(\@new_array);
据我所知,当它迭代时,它将取(1..10)的第一个值,即1,并将其传递给如下函数:
my @array = somefunc(1);
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
for my $i (1..10) {
my @count;
my @array = somefunc($i);
print "The array is Dumper(@array)\n";
$count[$i] = scalar @array;
print Dumper($count[$i]);
}
sub somefunc {
my $a = shift;
return $a * $a;
}
由于该函数没有定义,我将创建逻辑
sub somefunc {
my $a = shift;
print $a * $a;
}
这基本上可以做到:
1 * 1
结果是“1”
据我所知,我的@array将如下所示:
@array = ('1');
下一行可以:
$AoA[$i] = @array;
我假设$AoA[$1]是一个匿名数组(顺便说一句,他/她并没有用“我的”声明),并且@array将是这个匿名数组的第一个元素,作者说它“错了”。以及迭代到“2”的for each循环
somefunc(2);
将成为“4”并传递给:
$AoA[$i] = @array
作者对这段错误代码的看法是什么。我试图理解什么是错误的,但更重要的是,我试图理解代码。任何帮助都将不胜感激
更新
我想我理解为什么这是一个常见的错误,因为当我使用print和Dumper时,我可以直观地看到作者试图表达的内容,下面是修改后的代码
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
for my $i (1..10) {
my @AoA;
my @array = somefunc($i);
print "The array is Dumper(@array)\n";
$AoA[$i] = @array; # WRONG!
print Dumper($AoA[$i]);
}
sub somefunc {
my $a = shift;
return $a * $a;
}
在perldoc perldsc的“常见错误”一段中,他/她指出
在这种情况下,只需获取计数而不是嵌套数组:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my @count;
my @new_array;
for my $i (1..10) {
#my @count;
my @array = somefunc($i);
push @new_array, [@array];
}
sub somefunc {
my $a = shift;
return $a * $a;
}
print Dumper(\@new_array);
下面是转储程序的输出
The array is Dumper(1)
$VAR1 = 1;
The array is Dumper(4)
$VAR1 = 1;
The array is Dumper(9)
$VAR1 = 1;
The array is Dumper(16)
$VAR1 = 1;
The array is Dumper(25)
$VAR1 = 1;
The array is Dumper(36)
$VAR1 = 1;
The array is Dumper(49)
$VAR1 = 1;
The array is Dumper(64)
$VAR1 = 1;
The array is Dumper(81)
$VAR1 = 1;
The array is Dumper(100)
$VAR1 = 1;
所以我假设
$VAR1 = 1;
是计数,而不是嵌套数组
作者确实指出,如果计数是我真正想要的,那么重写代码如下:
my @array = somefunc(1);
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
for my $i (1..10) {
my @count;
my @array = somefunc($i);
print "The array is Dumper(@array)\n";
$count[$i] = scalar @array;
print Dumper($count[$i]);
}
sub somefunc {
my $a = shift;
return $a * $a;
}
但是文档没有告诉我如何获取嵌套数组 更新 如果我错了,请更正,但我重写了代码以获取嵌套数组:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my @count;
my @new_array;
for my $i (1..10) {
#my @count;
my @array = somefunc($i);
push @new_array, [@array];
}
sub somefunc {
my $a = shift;
return $a * $a;
}
print Dumper(\@new_array);
哪个印刷品
$VAR1 = [
[
1
],
[
4
],
[
9
],
[
16
],
[
25
],
[
36
],
[
49
],
[
64
],
[
81
],
[
100
]
];
在以下声明中:
$AoA[$i] = @array;
@array
在标量上下文中被引用,从而产生许多元素。上下文由LHS施加,即$AoA[$i]
,它是@AoA
数组的单个元素
在Perl中,没有严格意义上的数组数组。这些基本上是通过“展平”数组或带引用的数组来模拟的。对于后者,您需要使用take reference运算符,如中所示:
$AoA[$i] = \@array;
对于初学者,您可能会发现,这在检查复杂的数据结构(如arrayrefs和hashrefs)时非常方便。Perl是多态的,这意味着它可以透明地处理不同的数据类型,并且通常可以很好地猜测如何处理某些数据。这使得程序员的工作更加容易,因为它不像其他语言那样是强类型的 例如,如果$i是数字4,您可以这样做:
print $i + 1;
你会看到一个5-非常符合逻辑,对吗
如果你这样做:
print "I am " , $i , " years old";
您将看到“我4岁了”——在本例中,perl表示“您在列表上下文中操作,因此我将$I视为字符串。无需像许多其他语言所坚持的那样将数字转换为字符串 所以当你分配
$AoA[$i] = @array;
其处理方式取决于上下文。在标量上下文中,它将$AoA[$i]设置为数组的长度
有关标量与列表上下文的更多信息,请阅读以下答案:
您的示例对于理解这里发生的事情不是很有用,因为您的子例程总是返回“1”-调用
print()
的结果。如果将print()
替换为return()
,那么您将得到不同的值(1、4、9等)
但下一行代码:
$AoA[$i] = @array;
将始终将1
分配给@Aoa
的元素。这是因为您正在将数组(@array
)分配给标量变量($Aoa[$i]
),并且当您在标量上下文中计算数组时,会得到数组中的元素数
现在,由于您的@array
只有一个元素,您可以执行以下操作:
$AoA[$i] = $array[0];
但这并不是真正构建一个数组数组,你真正想做的是获取一个数组的引用
$AoA[$i] = \@array;
如果子例程返回多个值,这将更有用
sub somefunc {
# Used $x instead of $a as $a has a special meaning in Perl
my $x = shift;
return ($x * $x, $x * $x * $x);
}
for my $i (1..10) {
my @array = somefunc($i);
$AoA[$i] = \@array;
}
探索这一点的有用工具是。请尝试添加:
use Data::Dumper;
到代码的顶部,然后:
print Dumper @AoA;
在
foreach
循环之后,查看您返回的不同数据结构。我认为应该是返回$a*$a
,而不是打印$a*$a
。$AoA[$I]
引用常规数组@AoA
的$I
第个元素(作者未声明)。赋值$AoA[$i]=@array
在标量上下文中,所以@array
将计算为arrayRe的长度“@array将是此匿名数组的第一个元素“,否,@array
在标量上下文中计算为@array
中的元素数。请注意,该示例试图演示如何将@array
放置在@AoA
的元素中,因此sub somefunc{my$i=shift;return($i*2,$i*3);}
将是一个更好的示例。“文档没有告诉我如何获取嵌套数组”。但我们的许多答案都告诉了我。$AoA[$i]=\@array;
。使用转储程序打印@AoA
,看看你得到了什么。很好,在javascript中花费的时间太多了。应该使用“.”运算符,但随后它显式地执行串联:)“你正在列表上下文中操作,因此,我将把$I视为一个字符串”。列表上下文没有说明值是被视为数字还是字符串。将其所有参数转换为字符串的是print()
。如果将逗号替换为点,则$I
将无效