perllol 操作数组 在 Perl 中构建的最简单的两级数据结构是数组的数组,有时随便称为列表列表。

您所在的位置:网站首页 指针数组定义方法 perllol 操作数组 在 Perl 中构建的最简单的两级数据结构是数组的数组,有时随便称为列表列表。

perllol 操作数组 在 Perl 中构建的最简单的两级数据结构是数组的数组,有时随便称为列表列表。

#perllol 操作数组 在 Perl 中构建的最简单的两级数据结构是数组的数组,有时随便称为列表列表。| 来源: 网络整理| 查看: 265

perllol CONTENTS NAME DESCRIPTION 数组数组的声明和访问 自己种植 访问和打印 Slices SEE ALSO AUTHOR NAME

perllol-在Perl中操纵数组的数组。

DESCRIPTION 数组数组的声明和访问

在Perl中构建的最简单的两级数据结构是一个数组,有时也会被随便称为列表的列表。它相当容易理解,几乎这里适用的所有内容也都适用于后面的更高级的数据结构。

数组的数组只是一个常规的旧数组@AoA,您可以使用两个下标来获取它们,例如 $AoA[3][2] 。这是数组的声明:

use v5.10; # 所以我们可以使用 say() # 分配给我们的数组,一个数组引用的数组 @AoA = ( [ "fred", "barney", "pebbles", "bambam", "dino", ], [ "george", "jane", "elroy", "judy", ], [ "homer", "bart", "marge", "maggie", ], ); say $AoA[2][1]; bart

现在你应该非常小心,外括号类型是一个圆括号,也就是括号。这是因为你要分配给一个@array,所以你需要括号。如果你想要有not为了成为一个@AoA,而只是一个参考,你可以做一些更像这样的事情。

# 分配对数组引用数组的引用 $ref_to_AoA = [ [ "fred", "barney", "pebbles", "bambam", "dino", ], [ "george", "jane", "elroy", "judy", ], [ "homer", "bart", "marge", "maggie", ], ]; say $ref_to_AoA->[2][1]; bart

请注意,外括号类型已更改,因此我们的访问语法也已更改。那是因为与C不同,在Perl中,您不能自由地交换数组及其引用。 $ ref_to_AoA是对数组的引用,而@AoA是适当的数组。同样, $AoA[2] 不是数组,而是数组ref。那么你怎么能写这些:

$AoA[2][2] $ref_to_AoA->[2][2]

而不是要写这些。

$AoA[2]->[2] $ref_to_AoA->[2]->[2]

好吧,那是因为规则是只在相邻的括号上(不管是方括号还是卷括号),你可以自由地省略指针去参考箭头。但是如果是一个包含引用的标量,你就不能对第一个标量这样做,这意味着$ref_to_AoA总是需要它。

自己种植

对于固定数据结构的声明来说,这一切都很好,但如果你想在飞行中添加新的元素,或者完全从头开始建立它呢?

首先,我们来看看从文件中读进去。这就像一次添加一行一样。我们假设有一个平面文件,其中每行是一行,每个字是一个元素。如果你想开发一个包含所有这些内容的@AoA数组,这里有一个正确的方法。

while () { @tmp = split; push @AoA, [ @tmp ]; }

你也可能是从一个函数中加载的。

for $i ( 1 .. 10 ) { $AoA[$i] = [ somefunc($i) ]; }

或者你可能有一个临时变量和数组放在一起。

for $i ( 1 .. 10 ) { @tmp = somefunc($i); $AoA[$i] = [ @tmp ]; }

确保使用 [ ] 数组引用构造函数很重要。那是因为这行不通:

$AoA[$i] = @tmp; # WRONG!

之所以不能如你所愿,是因为把这样一个命名的数组赋给一个标量,就是在标量上下文中取一个数组,也就是只计算@tmp中的元素数。

如果您 use strict (如果不是,那么,为什么呢?),您必须添加一些声明使其满意:

use strict; my(@AoA, @tmp); while () { @tmp = split; push @AoA, [ @tmp ]; }

当然,你根本不需要临时数组有名字。

while () { push @AoA, [ split ]; }

你也不必使用push()。如果你知道你想把它放在哪里,你可以直接进行赋值。

my (@AoA, $i, $line); for $i ( 0 .. 10 ) { $line = ; $AoA[$i] = [ split " ", $line ]; }

甚至只是

my (@AoA, $i); for $i ( 0 .. 10 ) { $AoA[$i] = [ split " ", ]; }

一般来说,你应该谨慎使用可能在标量上下文中返回列表的函数,而不明确说明。这对普通读者来说会更清楚。

my (@AoA, $i); for $i ( 0 .. 10 ) { $AoA[$i] = [ split " ", scalar() ]; }

如果你想让$ref_to_AoA变量作为一个数组的引用,你必须做这样的事情。

while () { push @$ref_to_AoA, [ split ]; }

现在你可以添加新的行了。那添加新的列呢?如果你只处理矩阵,通常使用简单赋值是最简单的。

for $x (1 .. 10) { for $y (1 .. 10) { $AoA[$x][$y] = func($x, $y); } } for $x ( 3, 7, 9 ) { $AoA[$x][20] += func2($x); }

这些元素是否已经存在都没有关系:它将为您高兴地创建它们,并根据需要将中间元素设置为 undef 。

如果你只想追加到一行,你就得做一些看起来更有趣的事情。

# 向现有行添加新列 push $AoA[0]->@*, "wilma", "betty"; # 显式解引用 访问和打印

现在是时候把你的数据结构打印出来了。你要怎么做呢?如果你只想要其中一个元素,这很简单。

print $AoA[0][0];

不过,如果你想把整个事情打印出来,你不能说

print @AoA; # WRONG

因为你会得到的只是列出的引用,而perl永远不会自动为你解除引用。相反,你必须给自己滚一两个循环。这将打印整个结构,使用 shell 风格的 for()构造在外层的下标集上循环。

for $aref ( @AoA ) { say "\t [ @$aref ],"; }

如果你想跟踪订阅,你可以这样做。

for $i ( 0 .. $#AoA ) { say "\t elt $i is [ @{$AoA[$i]} ],"; }

甚至可能是这个。注意内环。

for $i ( 0 .. $#AoA ) { for $j ( 0 .. $#{$AoA[$i]} ) { say "elt $i $j is $AoA[$i][$j]"; } }

如你所见,它变得有点复杂。所以有时候在你的路上临时抱佛脚是比较容易的。

for $i ( 0 .. $#AoA ) { $aref = $AoA[$i]; for $j ( 0 .. $#{$aref} ) { say "elt $i $j is $AoA[$i][$j]"; } }

嗯......还是有点难看。那这个呢?

for $i ( 0 .. $#AoA ) { $aref = $AoA[$i]; $n = @$aref - 1; for $j ( 0 .. $n ) { say "elt $i $j is $AoA[$i][$j]"; } }

当您厌倦了为数据结构编写自定义打印时,可以查看标准的Dumpvalue或Data :: Dumper模块。前者是Perl调试器使用的东西,而后者则生成可分析的Perl代码。例如:

use v5.14; # 使用 + 原型,v5.14 新增 sub show(+) { require Dumpvalue; state $prettily = new Dumpvalue:: tick => q("), compactDump => 1, # 注释这两行 # out veryCompact => 1, #如果你想要更大的 # dump ; dumpValue $prettily @_; } # 将数组引用列表分配给数组。 my @AoA = ( [ "fred", "barney" ], [ "george", "jane", "elroy" ], [ "homer", "marge", "bart" ], ); push $AoA[0]->@*, "wilma", "betty"; show @AoA;

会打印出来。

0 0..3 "fred" "barney" "wilma" "betty" 1 0..2 "george" "jane" "elroy" 2 0..2 "homer" "marge" "bart"

而如果你把我说的那两行字注释出来,你可能会希望,那么它反而会这样显示给你。

0 ARRAY(0x8031d0) 0 "fred" 1 "barney" 2 "wilma" 3 "betty" 1 ARRAY(0x803d40) 0 "george" 1 "jane" 2 "elroy" 2 ARRAY(0x803e10) 0 "homer" 1 "marge" 2 "bart" Slices

如果你想在一个多维数组中获取一个切片(行的一部分),你将不得不做一些花哨的下标。这是因为,虽然我们有一个很好的同义词,可以通过指针箭头来实现单元素的取消引用,但对于切片却没有这样的便利。

下面是如何使用循环进行一个操作。我们和之前一样假设一个@AoA变量。

@part = (); $x = 4; for ($y = 7; $y < 13; $y++) { push @part, $AoA[$x][$y]; }

同样的循环可以用分片操作代替。

@part = $AoA[4]->@[ 7..12 ];

现在,如果你想要一个two-dimensional slice,例如$ x从4..8运行而$ y从7运行至12?嗯...这是简单的方法:

@newAoA = (); for ($startx = $x = 4; $x 8, 7 => 12 ); sub splice_2D { my $lrr = shift; # ref 到数组 refs 的数组! my ($x_lo, $x_hi, $y_lo, $y_hi) = @_; return map { [ $lrr->[$_]->@[ $y_lo .. $y_hi ] ] } $x_lo .. $x_hi; }SEE ALSO

perldata, perlref, perldsc

AUTHOR

汤姆·克里斯蒂安森

最后更新:Tue Apr 26 18:30:55 MDT 2011

Perl 5.36 Other categories Examples perlmacosx perlmod

1 … 624 625 626 627 628 … 1088 Next



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3