了解perl中的数据结构

时间:2016-11-06 20:05:26

标签: perl

我正在尝试理解perldsc文档中的“常见错误”部分。当他提到时,作者试图传达的是什么:

  

构造类似数组的两个最常见的错误是要么意外地计算元素的数量,要么重复引用相同的内存位置。在这种情况下,您只需获取计数而不是嵌套数组:

for my $i (1..10) {
    my @array = somefunc($i);
    $AoA[$i] = @array;      # WRONG!
}

根据我的理解,当它迭代时,它将取第一个值(1..10),即1,并将它传递给这样的函数:

my @array = somefunc(1);

由于未定义该功能,我将创建逻辑。

sub somefunc  {
my $a = shift;
print $a * $a;
}

基本上会这样做:

1 * 1

,结果为'1'。

据我所知,我的@array看起来像:

@array = ('1');

下一行将会:

$AoA[$i] = @array;

我假设$ AoA [$ 1]是一个匿名数组(他/她没有用'my',btw声明),@ array将是这个匿名数组的第一个元素,作者说它错了。并为每个循环迭代到'2'。

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的Common Mistakes段落中,他/她陈述

  

在这种情况下,您只需获取计数而不是嵌套数组:

以下是翻斗车的输出。

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;

是计数而不是嵌套数组。

作者确实指出,如果计数是我真正想要的,那么就像这样重写代码:

#!/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
      ]
    ];

3 个答案:

答案 0 :(得分:6)

在以下声明中:

$AoA[$i] = @array;

标量上下文中引用了@array,产生了许多元素。上下文由LHS强加,即$AoA[$i],它是@AoA数组的单个元素。

在Perl中,严格意义上没有数组数组。它们基本上由“扁平”数组或带引用的数组模拟。对于后者,您需要使用take reference运算符,如:

$AoA[$i] = \@array;

对于入门者,您可能会发现,Data::Dumper在检查复杂数据结构(如arrayrefs和hashrefs)时非常方便。

答案 1 :(得分:1)

Perl是多态的,这意味着它透明地处理不同的数据类型,并且通常可以很好地猜测如何处理某些事情。这使得程序员的工作变得更加容易,因为它不像其他语言那样强类型化。

因此,例如,如果$ i是数字4,您可以这样做:

print $i + 1;

你会看到一个5 - 很合乎逻辑,对吗?

如果你这样做:

print "I am " , $i , " years old";

你会看到"我4岁" - 在这种情况下perl说"你在列表上下文中操作,所以我将$ i视为一个字符串。无需像许多其他语言所坚持的那样将数字转换为字符串。

所以当你指定

$AoA[$i] = @array;

它对待它的方式取决于上下文。在标量上下文中,它将$ AoA [$ i]设置为数组的长度。

有关标量与列表上下文的更多信息,请阅读以下答案:

http://perl.plover.com/context.html

答案 2 :(得分:1)

你的例子对于理解这里发生的事情并不是很有用,因为你的子程序总是返回“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;
}

作为探索此问题的有用工具是https://facebook.github.io/react-native/docs/navigator.html。尝试添加:

use Data::Dumper;

到代码的顶部,然后:

print Dumper @AoA;

foreach循环之后,查看您获得的不同数据结构。