[PERL] 08-陣列 #2 --操作

URL Link //n.sfs.tw/11675

2017-08-22 01:26:20 By 張○○

陣列的第二單元有更多陣列的操作,在PERL裡面會常用到

 

陣列的合併

合併陣列用清單的方式即可

@reds =qw(red pink purple);
@blues = qw(blue cyan navy);

@color = (@reds, @blues);
print "@color\n"; # red pink purple blue cyan navy

這裡觀察到 PERL直接把兩個陣列作黏合,並非陣列中的陣列

在PERL中的陣列都是一維陣列,除非使用參照的方法,否則無論怎麼結合都是一元陣列。

抽出陣列

[PERL] 06-運算子 #2 的範圍運算子中有提過很簡單的方法就能抽出一段陣列

@slice= @array[4..12];  #切出第4到第12
@slice= @array[-5..-1];  #切出倒數第5到尾端
@slice= @array[0,3,4,6];  #切出第0,3,4,5項

字串和陣列

字串轉陣列

$str = "12,13,44,56,75,23";;
print @num= split(/,/, $str);

在split這個函式中的分隔判斷是採用比對的方式,這樣給程式非常多的彈性,不再限於單一字元或類型。

例如假設得到一個姓名的字串,名字中有空白、或定位字元,而且前後都有多個空白字元:

  $str= "  John<定位字元>Mary  Janny Peter  ";

一體適用當成同一分隔來拆開

@name = split(/\s+/, $str);
print "@name"; # John Mary Janny Peter

這在剖析檔案時很好用,上面的第2行,比對的樣式為 [,\s]+ ,在04-基本比對 有提到過

      \s 在PERL代表了 空白和定位字元
      + 是出現一個以上,所以多個連續字元的話還是視為一個。

@name 拆出來的結果:

  ('', 'John', 'Mary',  'Janny', 'Peter)

字串前面因為有一個空白,所以會多拆一個空字元陣列,也許要解決這個方法很簡單,只要先把字串給trim就行了

  $str= trim( $str); # 誤!

當然你會得到錯誤,因為PERL沒有提供這樣的函數,其實也不必要,如果你的確想用這樣的函數,可以參考 [PERL] 自寫 trim, ltrim, rtrim 函數我寫的方法。

其實在PERL可以用更簡單的方法來達成,樣式改成這樣即可:

@name = split(' ', $str);

這裡用 ' '來代替 /\s+/,這兩個是等義的,但在split 函數有對 ' ' 多特別的待遇,會略過一開始的空白或定位。

陣列轉字串

@num = (12,13,15,17,18,20,201,204,300);
print $str = join(',', @num); # 12,13,15,17,18,20,201,204,300

陣列的操作

陣列有幾種操作方法

push 從後面加入

pop  從後面抽出

shift 從最前面抽出,後面項目往前遞補

unshift 從最前面加入,後面項目往後擠

splice 刪除項目,從指定位置塞入項目

直接看範例

@solar = qw(sun mercury venus earth moon);
push @solar, 'mars';  # sun mercury venus earth moon mars

@solar = qw(sun mercury venus earth moon);
pop @solar;  # sun mercury venus earth

@solar = qw(sun mercury venus earth moon);
shift @solar;  # mercury venus earth moon

@solar = qw(sun mercury venus earth moon);
unshift @solar, 'oort';  # oort sun mercury venus earth moon mars

splice 函數有多種參數,假設原本的陣列是

@solar = qw(sun mercury venus earth moon);

@removed就是被刪除或是抽出的陣列,所以也可以用這個函數抽出一段陣列,差別在於這個抽出後,原本的陣列項目就不見了。

# 刪除全部項目
@removed =splice( @solar);
# @solar=()
# @removed = (sun mercury venus earth moon)

# 從索引3處刪到尾端
@removed =splice( @solar,3);
# @solar= (sun mercury venus)
# @removed = (earth moon)

# 從索引1處刪除2個項目
@removed =splice( @solar,1,2); # sun earth moon
#  @solar=  (sun earth moon)
#  @removed = (mercury venus)

splice還能順便插入項目

# 從索引1處刪除3個項目,並把 @planets陣列塞進去
@planets = qw(jupiter saturn uranus neptune);
@removed =splice( @solar,1,3,@planets);
# @solar= (sun jupiter saturn uranus neptune moon) 
# @removed = (mercury venus earth)

刪除一個項目

刪除一個項目比較麻煩

錯誤方法,該項目為undef但依然存在

  $array[3]=undef;

正確方法,用splice

  splice( @array,索引值,1);

 

陣列排序

陣列的最後面寫排序,順向排序(a->z)用 sort,反向排序(z->a)用reverse+sort

@solar = qw(sun mercury venus earth moon);
@odr = sort(@solar);
@descodr = reverse(sort(@solar));
print "@solar\n";  #原來的順序和陣列不變 sun mercury venus earth moon
print "@odr\n"; # 順向排序的結果 earth mercury moon sun venus
print "@descodr\n"; # 順向排序的結果 venus sun moon mercury earth

自定排序

上面那種排序一定不夠用的,因為排序有很多種條件,例如我之前 [PHP] 陣列排序 sort, ksort, asort, usort... 舉過的例子,我希望能照  A K Q J 10 9..2的順序排序,我把程式改寫成PERL

@poker = (qw(A K Q J), 2..10);

@s = sort {
  $order= "AKQJ1098765432";
  index($order, $a) <=> index($order, $b);
}
@poker;

print "@poker\n";  #原來陣列不變 A K Q J 2 3 4 5 6 7 8 9 10
print "@s\n"; # 排序後的陣列 A K Q J 10 9 8 7 6 5 4 3 2

第1行 建立樸克的陣列,我懶得一個個打,所以用上面教的陣列相黏法來產生

第3行 排序後的陣列是@s,裡面用我自訂的排序方式:

@排序完陣列= sort { 自訂排序法 } @原陣列

我的自訂排序法只有二行,第5行定義順序,第6行使用函數 index,作用是尋找字串$a或$b在$order中的位置,再使用一個 05-運算子 #1 比較運算子中提過的數值比較運算 '<=>'即可。

自訂排序基本上就是比較進階的部分,因此點到為止。下一篇要寫PERL裡很有特色的雜湊。

上一篇 07-陣列 #1 -- 基本
回到目錄 01-撰寫第一隻PERL程式
下一篇 09-雜湊