4

()在 Perl 中使用与 example 有什么区别[]?当它使用方括号时如何找到数组的大小?

my @myarr = ( # Parenthesis
                [ "itemone", "itemoneb", "itemonec" ],
                [ "itemtwo", "itemtwob", "itemtwoc" ]
               );

my @myarr = [ # Square bracket
                [ "itemone", "itemoneb", "itemonec" ],
                [ "itemtwo", "itemtwob", "itemtwoc" ]
               ];

谢谢你的解释。我仍在努力理解这一点,目前这让我有点困惑。我仍然无法弄清楚如何在这里遍历我的数据:

#!/usr/bin/perl -w

use strict;
use FindBin qw($Bin);
use Cwd;
use Data::Dumper;

my @mynames = (
                [ "myname", "mydescription", "mydata"],
                [ "myname2", "mydescription2", "mydata2"],
                [ "myname3", "mydescription3", "mydata3"],
               );


go();

sub go {
    start(\@mynames);
}

sub start {
    my @input_name = shift;

    # This works
    #print @input_name->[0][0][0];
    #die;

    # This Shows
    #print Dumper(@input_name);
    #$VAR1 = [
    #          [
    #            'myname',
    #            'mydescription',
    #            'mydata'
    #          ],
    #          [
    #            'myname2',
    #            'mydescription2',
    #            'mydata2'
    #          ],
    #          [
    #            'myname3',
    #            'mydescription3',
    #            'mydata3'
    #          ]
    #        ];

    # How do I iterate?
    #for my $i (0..@$input_name) {
    #    my $name = "";
    #    my $description = "";
    #    my $data = "";
    #
    #}
}
4

4 回答 4

6

这是错误的:

my @myarr = [
                [ "itemone", "itemoneb", "itemonec" ],
                [ "itemtwo", "itemtwob", "itemtwoc" ]
               ];

它应该是:

my $myarr = [
                [ "itemone", "itemoneb", "itemonec" ],
                [ "itemtwo", "itemtwob", "itemtwoc" ]
               ];

上面是“$myarr”。方括号将返回对标量列表的引用。因此需要使用“$”而不是“@”。

或者

my @myarr = (
                [ "itemone", "itemoneb", "itemonec" ],
                [ "itemtwo", "itemtwob", "itemtwoc" ]
               );

它是上面的“()”而不是“[]”。“()”将返回列表,因此它需要“@”。

检查以下迭代 AoA 的代码。这样您就可以访问 AoA 的所有元素。以及个别元素:

#!/usr/bin/perl -w
use strict;

my @mynames = (
                [ "myname", "mydescription", "mydata"],
                [ "myname2", "mydescription2", "mydata2"],
                [ "myname3", "mydescription3", "mydata3"],
              );

### To access all the elements in above AoA
foreach my $a (@mynames)
{
    foreach my $b ( @{$a} )
    {
        print $b."\t";
    }
    print "\n";
}
print "====================================\n";

### To access individual elements:
print $mynames[1][2]."\n"; ### It prints mydata2

您可能想阅读perlref来学习和理解 Perl 引用和嵌套数据结构。

于 2012-10-30T06:51:05.493 回答
2

括号不会创建数组,甚至不会创建列表。让我们对您的代码进行有意义的比较:

my @myarr1 = (
                [ "itemone", "itemoneb", "itemonec" ],
                [ "itemtwo", "itemtwob", "itemtwoc" ]
             );

my @myarr2 = (
                [
                   [ "itemone", "itemoneb", "itemonec" ],
                   [ "itemtwo", "itemtwob", "itemtwoc" ]
                ],
             );

@myarr1是具有两个元素的 AoA。
@myarr2是具有一个元素的 AoAoA。

要查找 引用的数组的大小$myarr2[0],您可以在标量上下文中使用以下内容:

@{ $myarr2[0] }

也就是说,您可能打算使用

my $myarr2 = [
                [ "itemone", "itemoneb", "itemonec" ],
                [ "itemtwo", "itemtwob", "itemtwoc" ]
             ];

在这种情况下,您将在标量上下文中使用以下内容:

@$myarr2     # Short for @{ $myarr2 }
于 2012-10-30T06:47:40.097 回答
1

这是对更新问题的答案,该问题是关于如何遍历多维数组

数组数组

my @mynames = (
    [qw(myname  mydescription  mydata )], # the same as 'myname', 'my...', ...
    [qw(myname2 mydescription2 mydata2)],
    [qw(myname3 mydescription3 mydata3)],
);

(正如评论所述,qw(foo bar)这只是一种奇特的编写方式'foo', 'bar'。)这基本上是一个 AoA(数组的数组),可以这样使用:

愚蠢的迭代

foreach my $row (@mynames) {
    foreach my $col (@$row) {
        say $col;
    }
    say 'done with this row';
}

输出:

myname
mydescription
mydata
done with this row
myname2
mydescription2
mydata2
done with this row
myname3
mydescription3
mydata3
done with this row

但我们确实对这个 AoA 了解得更多:

不是那么愚蠢的迭代

foreach my $row (@mynames) {
    say join ', ' => @$row;
}

输出:

myname, mydescription, mydata
myname2, mydescription2, mydata2
myname3, mydescription3, mydata3

$row是一个数组引用,要在 中使用它的列表值join,我们必须用@$row. 但我们可以做得更好:

我们对这里的结构了解更多

foreach my $row (@mynames) {
    say "name: $row->[0], description: $row->[1], data: $row->[2]";
}

输出:

name: myname, description: mydescription, data: mydata
name: myname2, description: mydescription2, data: mydata2
name: myname3, description: mydescription3, data: mydata3

我们知道第一项是名称,第二项是描述,第三项是某种数据值,所以我们可以在输出中简单地告诉用户这个事实。$row->[42]是访问数组 ref 中的单个值的方法,与使用简单数组进行相同的操作相比$array[42]

但我们可以做得更好!

哈希哈希

正如我们对我们的结构所了解的那样,最好使用散列哈希 (HoH) 来表达这个结构。由于第一项似乎是其余项的某种(希望是唯一的)名称,我们可以将其用作哈希键,而描述和数据进入新的哈希引用:

my %data = (
    myname  => {description => 'foo', data => 42},
    myname2 => {description => 'bar', data => 17},
    myname3 => {description => 'baz', data => 37},
);

现在迭代数据感觉好多了,代码更具可读性和健壮性:

foreach my $name (keys %data) {
    say "name       : $name";
    say "description: $data{$name}{description}";
    say "data       : $data{$name}{data}";
}

输出:

name       : myname
description: foo
data       : 42
name       : myname3
description: baz
data       : 37
name       : myname2
description: bar
data       : 17

但是,如您所见,输出不再排序。也许这不是问题,但如果你想定义一个订单,你可以用sort. 使用这种灵活的构造,您可以例如按一些特定的数据值排序:

按数据排序

foreach my $name (sort {$data{$a}{data} <=> $data{$b}{data}} keys %data) {
    say "name       : $name";
    say "description: $data{$name}{description}";
    say "data       : $data{$name}{data}";
}

输出:

name       : myname2
description: bar
data       : 17
name       : myname3
description: baz
data       : 37
name       : myname
description: foo
data       : 42

在perldoc -f sort中阅读有关其工作原理的更多信息。

哈希数组

如果你的名字不是唯一的,你可以使用这样的哈希数组:

my @data = (
    {name => 'myname', description => 'mydescription', data => 'mydata'},
    # ...
);

我把它作为一个简单的练习留给读者如何操作这个结构。希望能帮助到你!

更多阅读

perlreftut - MJD 关于引用的简短教程
perlref - Perl 引用和嵌套数据结构
perldsc - perl 数据结构说明书

于 2012-10-30T11:05:23.323 回答
0

方括号[]创建对列表的引用,而括号仅创建一个列表。

引用就像一个指针,必须取消引用才能获得它引用的列表。引用是一个标量值,这意味着您可以将它存储在一个标量变量中。您使用@前缀来取消引用列表引用,这将为您返回一个列表。

您还可以使用运算符创建引用\,例如:

[ a,b,c ] is the same as \@a if @a = (a,b,c)

例子:

my $a = [5,3,1];    # @$a is the same as (5,3,1)
push(@$a, 10);      # @$a is now (5,3,1,10)
join('-', @$a);     # "5-3-1-10"

say $a->[1];        # Prints "3" - an example of indexing
say $$a[1];         # Also prints "3"

sub foo { my $x = shift; say "Your list has ", scalar(@$x), " elements" }

foo($a);            # Prints: Your list has 4 elements

sub same_length { my ($x, $y) = @_; scalar(@$x) == scalar(@$y) }

same_length( $a, [6,7,8] );    # Returns false
same_length( $a, $a );         # Returns true

请注意same_length示例中我们如何将两个列表(通过使用引用)传递给子例程。这是使用引用的主要原因之一。

于 2012-10-30T06:46:21.550 回答