加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Perl 二维数组教程

发布时间:2020-12-16 00:29:31 所属栏目:大数据 来源:网络整理
导读:非常简短的(9php.com)一个二维数组教程,由鄙人翻译完成。 最新版本可以从这里获取(POD 格式): http://svn.perlchina.org/trunk/POD2-CN/lib/POD2/CN/perllol.pod [code]NAME ? ? perllol - 操作数组的(9php.com)数组(二维数组) 说明 ? 声明和访问
非常简短的(9php.com)一个二维数组教程,由鄙人翻译完成。 最新版本可以从这里获取(POD 格式): http://svn.perlchina.org/trunk/POD2-CN/lib/POD2/CN/perllol.pod [code]NAME ? ? perllol - 操作数组的(9php.com)数组(二维数组) 说明 ? 声明和访问数组的(9php.com)数组 ? ? 创建一个数组的(9php.com)数组(有时也可以叫“列表的(9php.com)列表”,不过不太准确)真是再简 ? ? 单也不过了。它相当容易理解,并且本文中出现的(9php.com)每个例子都有可能在实际应用 ? ? 中出现。 ? ? 数组的(9php.com)数组就是一个普通的(9php.com)数组(@AoA),不过可以接受两个下标("$AoA[3][2])。 ? ? 下面先定义一个这样的(9php.com)数组: " ? ? ? ? # 一个包含有“指向数组的(9php.com)引用”的(9php.com)数组 ? ? ? ? @AoA = ( ? ? ? ? ? ? [ "fred", "barney" ], ? ? ? ? ? ? [ "george", "jane", "elroy" ], ? ? ? ? ? ? [ "homer", "marge", "bart" ], ? ? ? ? ); ? ? ? ? print $AoA[2][2]; ? ? ? bart ? ? 你可能已经注意到,外面的(9php.com)括号是圆括号,这是因为我们想要给数组赋值,所以 ? ? 需要圆括号。如果你*不*希望这里是 @AoA,而是一个指向它的(9php.com)引用,那么就得 ? ? 这样: ? ? ? ? # 一个指向“包含有数组引用的(9php.com)数组”的(9php.com)引用 ? ? ? ? $ref_to_AoA = [ ? ? ? ? ? ? [ "fred", "barney", "pebbles", "bambam", "dino", ], ? ? ? ? ? ? [ "homer", "bart", "marge", "maggie", ], ? ? ? ? ? ? [ "george", "jane", "elroy", "judy", ], ? ? ? ? ]; ? ? ? ? print $ref_to_AoA->[2][2]; ? ? 注意外面的(9php.com)括号现在变成了方括号,并且我们的(9php.com)访问语法也有所改变。这时因为 ? ? 和 C 不同,在 Perl 中你不能自由地交换数组和引用(在 C 中,数组和指针在 ? ? 很多地方可以互相代替使用)。$ref_to_AoA 是一个数组引用,而 @AoA 是一个 ? ? 数组。同样地,$AoA[2] 也不是一个数组,而是一个数组引用。所以下面这 ? ? 两行: ? ? ? ? $AoA[2][2] ? ? ? ? $ref_to_AoA->[2][2] ? ? 也可以用这两行来代替: ? ? ? ? $AoA[2]->[2] ? ? ? ? $ref_to_AoA->[2]->[2] ? ? 这是因为这里有两个相邻的(9php.com)括号(不管是方括号还是花括号),所以你可以随意 ? ? 地省略箭头符号。但是如果 $ref_to_AoA 后面的(9php.com)那个箭头不能省略,因为省略 ? ? 了就没法知道 $ref_to_AoA 到底是引用还是数组了 ^_^。 ? 修改二维数组 ? ? 前面的(9php.com)例子里我们创建了包含有固定数据的(9php.com)二维数组,但是如何往其中添加新元 ? ? 素呢?再或者如何从零开始创建一个二维数组呢? ? ? 首先,让我们试着从一个文件中读取二维数组。首先我们演示如何一次性添加一 ? ? 行。首先我们假设有这样一个文本文件:每一行代表了二维数组的(9php.com)行,而每一个 ? ? 单词代表了二维数组的(9php.com)一个元素。下面的(9php.com)代码可以把它们储存到 @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 ]; ? ? ? ? } ? ? 注意方括号 "[]" 在这里非常重要。方括号实际上是数组引用的(9php.com)构造器。如果不 ? ? 用方括号而直接写,那就犯了很严重的(9php.com)错误: ? ? ? ? $AoA[$i] = @tmp; ? ? 你看,把一个数组赋值给了一个标量,那么其结果只是计算了 @tmp 数组的(9php.com)元素个 ? ? 数,我想这肯定不是你希望的(9php.com)。 ? ? 如果你打开了 "use strict",那么你就得先定义一些变量然后才能避免警告: ? ? ? ? use strict; ? ? ? ? my(@AoA, @tmp); ? ? ? ? while (<>) { ? ? ? ? ? ? @tmp = split; ? ? ? ? ? ? push @AoA, [ @tmp ]; ? ? ? ? } ? ? 当然,你也可以不要临时变量: ? ? ? ? while (<>) { ? ? ? ? ? ? push @AoA, [ split ]; ? ? ? ? } ? ? 如果你知道想要放在什么地方的(9php.com)话,你也可以不要 push(),而是直接进行赋值: ? ? ? ? my (@AoA, $i, $line); ? ? ? ? for $i ( 0 .. 10 ) { ? ? ? ? ? ? $line = <>; ? ? ? ? ? ? $AoA[$i] = [ split ' ', $line ]; ? ? ? ? } ? ? 甚至是这样: ? ? ? ? my (@AoA, $i); ? ? ? ? for $i ( 0 .. 10 ) { ? ? ? ? ? ? $AoA[$i] = [ split ' ', <> ]; ? ? ? ? } ? ? 你可能生怕 <> 在列表上下文会出差错,所以想要明确地声明要在标量上下文中 ? ? 对 <> 求值,这样可读性会更好一些: (译者注:列表上下文中,<> ? ? 返回所有的(9php.com)行,标量上下文中 <> 只返回一行。) ? ? ? ? my (@AoA, $i); ? ? ? ? for $i ( 0 .. 10 ) { ? ? ? ? ? ? $AoA[$i] = [ split ' ', scalar(<>) ]; ? ? ? ? } ? ? 如果你想用 $ref_to_AoA 这样的(9php.com)一个引用来代替数组,那你就得这么写: ? ? ? ? while (<>) { ? ? ? ? ? ? push @$ref_to_AoA, [ split ]; ? ? ? ? } ? ? 现在你已经知道如何添加新行了。那么如何添加新列呢?如果你正在做数学中的(9php.com) ? ? 矩阵运算,那么要完成类似的(9php.com)任务: ? ? ? ? for $x (1 .. 10) { ? ? ? ? ? ? for $y (1 .. 10) { ? ? ? ? ? ? ? ? $AoA[$x][$y] = func($x, $y); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? for $x ( 3, 7, 9 ) { ? ? ? ? ? ? $AoA[$x][20] += func2($x); ? ? ? ? } ? ? 想要访问的(9php.com)某个元素是不是存在是无关紧要的(9php.com):因为如果不存在那么 Perl 会给 ? ? 你自动创建!新创建的(9php.com)元素的(9php.com)值是 "undef"。 ? ? 如果你想添加到一行的(9php.com)末尾,你可以这么做: ? ? ? ? # 添加新列到已存在的(9php.com)行 ? ? ? ? push @{ $AoA[0] }, "wilma", "betty"; ? ? 注意我*没有*这么写: ? ? ? ? push $AoA[0], "wilma", "betty"; ?# 错误! ? ? 事实上,上面这句根本就没法通过编译!为什么?因为 push() 的(9php.com)第一个参数必 ? ? 须是一个真实的(9php.com)数组,不能是引用。 ? 访问和打印 ? ? 现在是打印二维数组的(9php.com)时候了。那么怎么打印?很简单,如果你只想打印一个元 ? ? 素,那么就这么来一下: ? ? ? ? print $AoA[0][0]; ? ? 如果你想打印整个数组,那你可不能这样: ? ? ? ? print @AoA; ? ? ? ? # 错误! ? ? 因为你这么做只能得到一列引用,Perl 从来都不会自动地为你解引用。作为替 ? ? 代,你必须得弄个循环或者是双重循环。用 shell 风格的(9php.com) for() 语句就可以 ? ? 打印整个二维数组: ? ? ? ? for $aref ( @AoA ) { ? ? ? ? ? ? print "t [ @$aref ],n"; ? ? ? ? } ? ? 如果你要用下标来遍历的(9php.com)话,你得这么做: ? ? ? ? for $i ( 0 .. $#AoA ) { ? ? ? ? ? ? print "t elt $i is [ @{$AoA[$i]} ],n"; ? ? ? ? } ? ? 或者这样用双重循环(注意内循环): ? ? ? ? for $i ( 0 .. $#AoA ) { ? ? ? ? ? ? for $j ( 0 .. $#{$AoA[$i]} ) { ? ? ? ? ? ? ? ? print "elt $i $j is $AoA[$i][$j]n"; ? ? ? ? ? ? } ? ? ? ? } ? ? 如同你看到的(9php.com)一样,它有点儿复杂。这就是为什么有时候用临时变量能够看起来 ? ? 更简单一些的(9php.com)原因: ? ? ? ? for $i ( 0 .. $#AoA ) { ? ? ? ? ? ? $aref = $AoA[$i]; ? ? ? ? ? ? for $j ( 0 .. $#{$aref} ) { ? ? ? ? ? ? ? ? print "elt $i $j is $AoA[$i][$j]n"; ? ? ? ? ? ? } ? ? ? ? } ? ? 哦,好像还有点复杂,那么试试这样: ? ? ? ? for $i ( 0 .. $#AoA ) { ? ? ? ? ? ? $aref = $AoA[$i]; ? ? ? ? ? ? $n = @$aref - 1; ? ? ? ? ? ? for $j ( 0 .. $n ) { ? ? ? ? ? ? ? ? print "elt $i $j is $AoA[$i][$j]n"; ? ? ? ? ? ? } ? ? ? ? } ? 切片 ? ? 切片是指数组的(9php.com)一部分。如果你想要得到多维数组的(9php.com)一个切片,那你得进行一些 ? ? 下标运算。通过箭头可以方便地为单个元素解引用,但是访问切片就没有这么好 ? ? 的(9php.com)事了。当然,我们可以通过循环来取切片。 ? ? 我们先演示如何用循环来获取切片。我们假设 @AoA 变量的(9php.com)值和前面一样。 ? ? ? ? @part = (); ? ? ? ? $x = 4; ? ? ? ? for ($y = 7; $y < 13; $y++) { ? ? ? ? ? ? push @part, $AoA[$x][$y]; ? ? ? ? } ? ? 这个循环其实可以用一个切片操作来代替: ? ? ? ? @part = @{ $AoA[4] } [ 7..12 ]; ? ? 不过这个看上去似乎略微有些复杂。 ? ? 下面再教你如何才能得到一个 *二维切片*, 比如 $x 从 4 到 8,$y 从 7 到 ? ? 12,应该怎么写? ? ? ? ? @newAoA = (); ? ? ? ? for ($startx = $x = 4; $x <= 8; $x++) { ? ? ? ? ? ? for ($starty = $y = 7; $y <= 12; $y++) { ? ? ? ? ? ? ? ? $newAoA[$x - $startx][$y - $starty] = $AoA[$x][$y]; ? ? ? ? ? ? } ? ? ? ? } ? ? 也可以省略掉中间的(9php.com)那层循环: ? ? ? ? for ($x = 4; $x <= 8; $x++) { ? ? ? ? ? ? push @newAoA, [ @{ $AoA[$x] } [ 7..12 ] ]; ? ? ? ? } ? ? 其实用 map 函数可以更加简练: ? ? ? ? @newAoA = map { [ @{ $AoA[$_] } [ 7..12 ] ] } 4 .. 8; ? ? 虽然你的(9php.com)经理也许会抱怨这种难以理解的(9php.com)代码可能会带来安全隐患, ? ? 然而这种观点还是颇有争议的(9php.com)(兴许还可以更加安全也说不定 ^_^)。 ? ? 换了是我,我会把它们放进一个函数中实现: ? ? ? ? @newAoA = splice_2D( @AoA, 4 => 8, 7 => 12 ); ? ? ? ? sub splice_2D { ? ? ? ? ? ? my $lrr = shift; ? ? ? ?# 指向二维数组的(9php.com)引用 ? ? ? ? ? ? my ($x_lo, $x_hi, ? ? ? ? ? ? ? ? $y_lo, $y_hi) = @_; ? ? ? ? ? ? return map { ? ? ? ? ? ? ? ? [ @{ $lrr->[$_] } [ $y_lo .. $y_hi ] ] ? ? ? ? ? ? } $x_lo .. $x_hi; ? ? ? ? } 参见 ? ? perldata(1), perlref(1), perldsc(1) 作者 ? ? Tom Christiansen <tchrist@perl.com> ? ? Last update: Thu Jun 4 16:16:23 MDT 1998 翻译者及翻译声明 ? ? 本文由 flw ("flw@cpan.org") 翻译,翻译成果首次出现在 *中国 Perl 协会* ? ? http://www.perlchina.org) 的(9php.com)协作开发平台上。 ? ? PerlChina.org 本着“在国内推广 Perl” 的(9php.com)目的(9php.com),组织人员翻译本文。读者可 ? ? 以在遵守原作者许可协议、尊重原作者及译作者劳动成果的(9php.com)前提下,任意发布或 ? ? 修改本文。 ? ? 本文作者用一种轻松地口吻简要介绍了一下二维数组的(9php.com)用法,但是正因如此,文 ? ? 中有些内容直译过来反而很拗口、很难懂(毕竟中西方文化不同嘛),因此译者 ? ? 在翻译时,对原文有较多的(9php.com)修改。喜欢阅读英文原版胜过喜欢翻译版的(9php.com)朋友们, ? ? 可以直接看原版 ^_^,同时也希望能够理解译者的(9php.com)一篇苦心,而不要在背后骂我 ? ? 翻译得不对就是了。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读