例如,在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 = "";
#
#}
}
答案 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(数组数组),可以像这样使用:
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
示例中请注意我们如何将两个列表(通过使用引用)传递给子例程。这是使用参考文献的主要原因之一。