找到多维数组大小

时间:2012-10-30 06:30:09

标签: perl multidimensional-array

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

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 个答案:

答案 0 :(得分:6)

这是错误的:

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

应该是:

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

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

OR

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 elemnts:
print $mynames[1][2]."\n"; ### It prints mydata2

您可能需要阅读perlref来学习和理解perl参考和嵌套数据结构。

答案 1 :(得分:2)

Parens不会创建数组,甚至列表。让我们展示您的代码的有意义的比较:

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 }

答案 2 :(得分: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(数组数组),可以像这样使用:

Dumb iterating

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]是访问数组引用中单个值的方法,与使用简单数组$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's very short tutorial about references
perlref - Perl references and nested data structures
perldsc - perl data structures cookbook

答案 3 :(得分:0)

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

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

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

[ 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示例中请注意我们如何将两个列表(通过使用引用)传递给子例程。这是使用参考文献的主要原因之一。