2013-01-07 15:17
1051人閱讀收藏
舉報本文和大家重點討論一下perl二維陣列的概念和用法,前面的例子裡我們建立了包含有固定資料的perl二維陣列,但是如何往其中新增新元素呢?再或者如何從零開始建立乙個perl二維陣列呢?本文回味大家一一講解。
perl二維陣列
最新版本可以從這裡獲取(pod格式):
perllol-運算元組的陣列(perl二維陣列)
宣告和訪問陣列的陣列
建立乙個陣列的陣列(有時也可以叫「列表的列表」,不過不太準確)真是再簡單也不過了。它相當容易理解,並且本文中出現的每個例子都有可能在實際應用中出現。
陣列的陣列就是乙個普通的陣列(@aoa),不過可以接受兩個下標("$aoa[3][2])。
下面先定義乙個這樣的陣列:"
#乙個包含有「指向陣列的引用」的陣列
my @aoa;
@aoa=(["fred","barney"],
["george","jane","elroy"],
["homer","marge","bart"],
);
print $aoa[2][2];
bart
你可能已經注意到,外面的括號是圓括號,這是因為我們想要給陣列賦值,所以需要圓括號。如果你不希望這裡是@aoa,而是乙個指向它的引用,那麼就得這樣:
#乙個指向「包含有陣列引用的陣列」的引用
my $ref_to_aoa;
$ref_to_aoa=[["fred","barney","pebbles","bambam","dino",],
["homer","bart","marge","maggie",],
["george","jane","elroy","judy",],
];
print $ref_to_aoa->[2][2];
注意外面的括號現在變成了方括號,並且我們的訪問語法也有所改變。這時因為和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]
這是因為這裡有兩個相鄰的括號(不管是方括號還是花括號),所以你可以隨意地省略箭頭符號。但是如果$ref_to_aoa後面的那個箭頭不能省略,因為省略了就沒法知道$ref_to_aoa到底是引用還是陣列了^_^。
修改perl二維陣列
前面的例子裡我們建立了包含有固定資料的perl二維陣列,但是如何往其中新增新元素呢?再或者如何從零開始建立乙個perl二維陣列呢?
首先,讓我們試著從乙個檔案中讀取perl二維陣列。首先我們演示如何一次性新增一行。首先我們假設有這樣乙個文字檔案:每一行代表了perl二維陣列的行,而每乙個單詞代表了perl二維陣列的乙個元素。下面的**可以把它們儲存到@aoa:
while(<>)
你也可以用乙個函式來一次讀取一行:
for $i(1..10)
或者也可以用乙個臨時變數來中轉一下,這樣看起來更清楚些:
for$i(1..10)
注意方括號""在這裡非常重要。方括號實際上是陣列引用的構造器。如果不用方括號而直接寫,那就犯了很嚴重的錯誤:$aoa[$i]=@tmp;
你看,把乙個陣列賦值給了乙個標量,那麼其結果只是計算了@tmp陣列的元素個數,我想這肯定不是你希望的。
如果你開啟了"use strict",那麼你就得先定義一些變數然後才能避免警告:
use strict;當然,你也可以不要臨時變數:my(@aoa,@tmp);
while(<
>)
while(<>)
如果你知道想要放在什麼地方的話,你也可以不要push(),而是直接進行賦值:
my(@aoa,$i,$line);for $i(0..10)
甚至是這樣:
my(@aoa,$i);for $i(0..10)
你可能生怕<>在列表上下文會出差錯,所以想要明確地宣告要在標量上下文中對<>求值,這樣可讀性會更好一些:(譯者注:列表上下文中,<>返回所有的行,標量上下文中<>只返回一行。)
my(@aoa,$i);
for $i(0..10)
如果你想用$ref_to_aoa這樣的乙個引用來代替陣列,那你就得這麼寫:
while(<>)
現在你已經知道如何新增新行了。那麼如何新增新列呢?如果你正在做數學中的矩陣運算,那麼要完成類似的任務:
for$x(1..10)} for $x(3,7,9)
想要訪問的某個元素是不是存在是無關緊要的:因為如果不存在那麼perl會給你自動建立!新建立的元素的值是"undef"。
如果你想新增到一行的末尾,你可以這麼做:
#新增新列到已存在的行
push @,"wilma","betty";
注意我*沒有*這麼寫:
push $aoa[0],"wilma","betty";#錯誤!
事實上,上面這句根本就沒法通過編譯!為什麼?因為push()的第乙個引數必須是乙個真實的陣列,不能是引用。
訪問和列印
現在是列印perl二維陣列的時候了。那麼怎麼列印?很簡單,如果你只想列印乙個元素,那麼就這麼來一下:
print$aoa[0][0];
如果你想列印整個陣列,那你可不能這樣:print@aoa;#錯誤!
因為你這麼做只能得到一列引用,perl從來都不會自動地為你解引用。作為替代,你必須得弄個迴圈或者是雙重迴圈。用shell風格的for()語句就可以列印整個perl二維陣列:
for $aref(@aoa)
如果你要用下標來遍歷的話,你得這麼做:
for $i(0..$#aoa)],\n";}
或者這樣用雙重迴圈(注意內迴圈):
for $i(0..$#aoa))}
如同你看到的一樣,它有點兒複雜。這就是為什麼有時候用臨時變數能夠看起來更簡單一些的原因:
for $i(0..$#aoa))}
哦,好像還有點複雜,那麼試試這樣:
for $i(0..$#aoa)}
切片
切片是指數組的一部分。如果你想要得到多維陣列的乙個切片,那你得進行一些下標運算。通過箭頭可以方便地為單個元素解引用,但是訪問切片就沒有這麼好的事了。當然,我們可以通過迴圈來取切片。
我們先演示如何用迴圈來獲取切片。我們假設@aoa變數的值和前面一樣。
@part=();
$x=4;
for($y=7;$y<13;$y++)
這個迴圈其實可以用乙個切片操作來代替:
@part= @[7..12];
不過這個看上去似乎略微有些複雜。
下面再教你如何才能得到乙個*二維切片*,比如$x從4到8,$y從7到12,應該怎麼寫?
@newaoa=();for($startx=$x=4;$x<=8;$x++)
}
也可以省略掉中間的那層迴圈:
for($x=4;$x<=8;$x++)[7..12] ];
}其實用map函式可以更加簡練:
@newaoa=map [7..12] ] }4..8;
雖然你的經理也許會抱怨這種難以理解的**可能會帶來安全隱患,然而這種觀點還是頗有爭議的(興許還可以更加安全也說不定^_^)。
換了是我,我會把它們放進乙個函式中實現:
@newaoa=splice_2d(\@aoa,4=>8,7=>12);subsplice_2d[$y_lo..$y_hi]]
}$x_lo..$x_hi;
}
perl 二維陣列
perl沒有真正的二維陣列,所謂的二維陣列其實是把一維陣列以引用的方式放到另外乙個一維陣列。二維陣列定義 my array1 1,2 3,4 45,9 66,5 使用表示匿名陣列 或者 my array2 qw this is a array my array3 another array my a...
Perl 二維陣列
7 切片 此處引用相當於c中的指標。二維陣列第一列不儲存具體元素而是儲存指向該行一維陣列的引用。my aoa fred barney pebbles bambam dino george jane elroy judy homer bart marge maggie ref to aoa fred ...
perl二維陣列
出處 7 切片 此處引用相當於c中的指標。二維陣列第一列不儲存具體元素而是儲存指向該行一維陣列的引用。my aoa fred barney pebbles bambam dino george jane elroy judy homer bart marge maggie ref to aoa fr...