Perl的列表和數組

列表和數組

列表

  • 使用括號包圍的元素,括號中的元素使用逗號隔開的是列表。
  • 列表中的元素能夠是字符串、數值、undef或它們的混合。
  • 列表中的字符串元素須要使用引號包圍。
  • 空列表是括號中什麼都沒有的列表,空列表返回的是undef。可是賦值給別人時,不會看成undef,而是什麼都沒有(見稍後的例子)。
(1,2,"perl","python")
("var1","var2","var3")
()       # 空列表
if(defined(())){        # 對空列表()進行判斷
    print "defined";
}else{
    print "undefined";  # 返回此行
}
  • Perl將忽略構造列表時多餘的逗號
(1,2,3,)      # 等價於(1,2,3)
(1,2,,,4)     # 等價於(1,2,4)
  • Perl會將多個列表壓扁(flatten)成一個大列表。例如:
    • ((1,2,3),("a","b","c"))會壓扁成(1,2,3,"a","b","c")
    • 這個特性用在不少地方,需注意。
  • 列表中的元素支持範圍操做,使用(..)便可。若是是小數,則取整。也支持負數。
  • 範圍操做不支持逆序範圍,但不會報錯。注意,不是undef,因此也就不是空列表。
  • Perl的範圍操做符強大的逆天。
(1..5)        # 等價於(1,2,3,4,5)
(1,2,3..5,7)  # 等價於(1,2,3,4,5,7)
(3.5..6)      # 等價於(3,4,5,6)
(3.5..6.5)    # 等價於(3,4,5,6)
(-3..2)       # 等價於(-3,-2,-1,0,1,2)
($m..$n)      # 範圍由$m和$n決定
(a..d)        # ("a","b","c","d")
/^one/ .. /^two/ # 匹配從one開頭的行到two開頭的行
/^one/ .. eof    # 匹配從one開頭的行到最後一行

其實範圍操做符有兩種:.....,它們只在匹配範圍的時候有區別。例如一段文本內容爲:php

start here end here
second line
end

若是使用/start/../end/,那麼在第一行就結束了匹配,由於第一行能同時匹配start和end,若是想要第一行匹配start,再也不匹配end,而是匹配第三行的end,那麼須要使用/start/.../end/。實際上,範圍操做符的左邊被匹配了稱爲flip,右邊被匹配了稱爲flop,三個點的範圍操做符...表示flip以後不要當即作flop評估,而是在本次以後評估flop。java

qw簡寫列表

使用qw寫列表,無需加引號,無需加逗號分隔,而是使用空格分隔。python

如下兩個列表等價:shell

("perl","python","shell")
qw(perl python shell)
  • qw裏雖然不用寫引號,但它至關於單引號。因此qw裏面不能變量替換,不能反斜線序列(如\n)
$perl="perl";
qw($perl python shell\n)   # 不會作任何轉換,包含三個元素"$perl"、"python"、"shell\n"
  • 由於會丟棄全部空白,因此能夠直接換行
qw(
    perl
    python
    shell
)

注意,不能在qw換行內部加上註釋#。因此,下面#和它後面的字符串也被看成列表元素數組

qw(
    perl
    python   # This is python
    shell
)
  • qw後面的定界符能夠換成其它的,只要對應就能夠。若是是括號類的,只要能結尾就能夠
qw/ var1 var2 var3 /
qw! var1 var2 var3 !
qw% var1 var2 var3 %
qw# var1 var2 var3 #      # 這個有點像註釋
...  
qw( var1 var2 var3 )
qw< var1 var2 var3 >
qw{ var1 var2 var3 }
qw[ var1 var2 var3 ]

若是定界符中間要包含定界符符號,只要轉義就能夠了。ruby

qw/ var1 var2 \/var3 var4 /

更好的方法是換成其它定界符。函數

qw{
    /root/xyz.sh
    /etc/xyz.sh
}

列表的賦值

  • perl中能夠經過列表一一對應地給(標量)變量賦值。
($perl,$python)=("perl","python");
print $perl,"\n";
print $python,"\n";
  • 賦值前,老是先計算出等號右邊的值,而後再賦給左邊。因此交換變量很是容易。
($perl,$python)=($python,$perl);
  • 若是列表賦值時,等號左右兩邊元素個數不等,則採起以下方案:
    • 若是右邊元素更多,則忽略多出來的元素;
    • 若是左邊變量元素更多,則多出來的變量賦值爲undef;
    ($perl,$python,$shell)     =qw(perl python shell php);   # php被忽略
    ($perl,$python,$shell,$php)=qw(perl python shell);  # $php被賦值爲undef
  • perl中,列表和數組緊密關聯。能夠認爲將列表賦值給一個變量,這個變量就是數組。數組使用"@"符號開頭。
print qw{perl python shell};
@subject=qw{perl python shell};
print @subject;
@subject=("perl","python","shell");
@range=1..5;
@subject=(@subject,"hello",@range);
  • 空列表和列表中的undef元素:
    • 空列表自身是一個未定義列表,因此它自身返回undef
    • 未定義的數組,或者未定義的列表就是空列表(),由於未定義,因此它自身返回undef
    • 將空列表或者未定義的數組做爲元素添加到其它列表、數組中時,等於什麼都沒作,直接被忽略,由於它是沒定義過的
    • undef元素是一個實實在在的元素,會佔用列表、數組空間
@empty=();
if(@empty){
    print "valid\n";
}else{
    print "invalid\n";    # 返回此行
}

@subject1=qw{perl python shell};
@subject2=(@subject,@empty,"php");  # 等價於(@subject,"php")
@subject3=(@subject,undef,"php");   # 不等價於(@subject,"php")

數組

  • 數組和列表中的元素,能夠是字符串、數值、undef或它們的混合,總之每一個元素都必須是標量(即不能嵌套數組、列表)。
  • 列表能夠單獨存在,但數組必須是由列表組成的,雖然它們都容許爲空。
  • 列表或數組中的元素, 字符串類型不須要使用引號包圍 (看下面的例子)。
  • perl中的數組使用"@"開頭,引用數組中元素的時候,使用"$"開頭,並帶上數組下標索引,就像變量同樣,其實就是引用數組變量(看下面的例子)。
  • 數組變量和普通變量的名稱屬於不通的名稱空間(namespace),因此perl中它們不會衝突,但對於人類來講,容易搞混。
  • 雙引號包圍數組時,會進行數組元素替換,每一個元素之間會自帶空格。若是不加引號包圍,輸出的時候,元素之間緊密相連,沒有空格。
$arr="xyz";
@arr=(var0,var1,var2);    # 這是一個列表,賦值給了數組。
                          # 列表中的元素沒有加引號包圍
print $arr[0],$arr[1],$arr[2],"\n";   # 引用數組變量
print $arr;             # 輸出xyz
print @arr,"\n";        # 輸出var0var1var2
print "@arr","\n"       # 輸出var0 var1 var2
  • 引用數組變量時,若是數組越界,不會報錯,而是返回undef值。但不會自動填充中間的元素。
  • 數組索引能夠是小數或負數,若是是小數,則自動取整。若是是負數,則從後向前取,超出數組範圍的負數,將返回undef。
  • $#arr表示最後一個索引值,它比數組元素個數小1(由於有個0索引)。因此$arr[$#arr]引用的是最後一個元素($arr[-1]也是最後一個元素)。
print $arr[1.3];     # 等價於$arr[1]
print $arr[-1];      # 最後一個元素
print $arr[-2];      # 倒數第二個元素
print $arr[100];     # undef
print $arr[-100];    # undef
print $arr[$#arr];   # 最後一個元素
print $arr[$#arr-1]; # 倒數第二個元素
  • 數組的標準引用方式是帶上大括號。例如@{arr}、$#{arr},這樣的引用方式能夠避免歧義。
@{arr1}=(var0,var1,var2)
  • perl中的數組在定義新元素的時候,會 自動填補中間缺乏的元素 ,這些元素被定義爲undef。
@arr2=(var0,var1,var2);
print $arr2[100];      # undef
print $#arr2;          # 返回2
$arr2[5]="var5"        # 將填充$arr2[3],$arr2[4]爲undef
print $#arr2;          # 返回5
  • 能夠直接引用數組,如@arr
  • perl中有不少種上下文環境,最常出現的是 標量上下文和列表上下文 。perl中會根據不一樣上下文進行轉換,從而獲取不同的值。後面會解釋這兩種上下文。

注意下面的例子中print @arr,"\n"print @arr."\n",僅僅是一個逗號和點號的區別,返回結果卻徹底不一樣。這就是不一樣上下文環境中的執行結果。spa

@arr=(var0,var1,var2);  # 數組,裏面的元素不用引號包圍
$arr[4]="var4";         # 直接對數組變量賦值,會自動填充$arr[3]:undef
print @arr,"\n";        # 引用整個數組:var0var1var2var4
print @arr."\n";        # 輸出的是5,表示的是數組中元素個數
                        # 由於這裏的數組從列表上下文切換成了標量上下文,
                        # 數組將返回元素個數

增、刪數組元素

pop、push

push函數:向數組尾部(最右邊)插入元素;
pop函數:彈出(移除並返回)數組尾部的元素;當沒有元素可彈時,則pop返回undef。code

pop和push用於實現堆棧,像堆盤子同樣,不斷往上堆,也從上面開始取。blog

@arr = 5..9;                   # (5,6,7,8,9)
$var1 = pop(@arr);
print @arr,"\n",$var1,"\n";    # 返回5678和9

$var2 = pop @arr;
print @arr,"\n",$var2,"\n";    # 返回567和8

pop @arr;                      # 直接丟棄彈出的元素
print @arr,"\n";               # 返回56

倒數第二行的pop @arr沒有作任何賦值,perl中有不少這種用法,當有返回內容時,卻不對其賦值,表示僅執行操做,但丟棄操做後的返回結果,在perl中,這種稱爲"空上下文"(void context)。因此,這裏能夠表示直接刪除數組的最後一個元素。

@arr=(5,6);
push(@arr,0);     # @arr如今是(5,6,0)
push @arr,1..10;  # @arr如今有13個元素:5,6,0,1,2,3,4,5,6,7,8,9,10
@other=qw{1 3 4 5};
push @arr,@other; # @arr如今17個元素:5,6,0,1,2,3,4,5,6,7,8,9,10,1,3,4,5

shift和unshift

push和pop是操做數組尾部,shift和unshift則是操做數組頭部:
- shift彈出(移除並返回)數組的第一個元素(最左邊),當沒有元素可彈時,shift將返回undef;
- unshift向數組最左邊插入一個元素。

@arr = qw{perl python shell};
$m   = shift(@arr);   # $m變成"perl",@arr如今是("python","shell")
$n   = shift @arr;    # $n變成"python",@arr如今是("shell")
shift @arr;           # @arr變成空了
%i   = shift @arr;    # $i爲undef,@arr仍是空
unshift @arr,5;       # @arr如今是(5)
unshift @arr,4;       # @arr如今是(4,5)
@other=1..3;
unshift @arr,@other;  # @arr如今變爲(1,2,3,4,5)

splice()函數

shift-unshift和pop-push操做的是數組首尾部。若是想要操做數組的中間某個元素,則須要使用splice()函數。

splice()函數有4個參數,後兩個參數可選。

  • 第一個參數指定要操做的數組;
  • 第二個參數指定從哪一個索引位置開始操做;
  • 第三個參數指定要操做的長度;
  • 第四個參數指定替換原數組的數據;

若是隻給兩個參數,則從索引位置開始,一直刪除到數組結尾。

# 兩個參數
@arr  = qw{perl python shell php java};
@arr1 = splice @arr,2;             # @arr如今是qw{perl python}
                                   # @arr1如今是qw{shell php java}

# 三個參數
@arr  = qw{perl python shell php java};
@arr1 = splice @arr,2,2;           # @arr如今是qw{perl python java}
                                   # @arr1如今是qw{shell php}

# 四個參數
@arr  = qw{perl python shell php java};
@arr1 = splice @arr,2,2,qw{ruby};    # @arr如今是qw{perl python ruby java}
                                     # @arr1如今是qw{shell php}

在使用四個參數的時候,若是將第三個參數設置爲0,則能夠不用作任何刪除就向數組中插入新元素。

@arr  = qw{perl python shell php java};
@arr1 = splice @arr,2,0,qw{ruby};   # @arr如今是qw{perl python ruby shell php java}
                                    # @arr1如今是qw()

foreach遍歷

foreach能夠遍歷列表或數組。

foreach $subject qw(perl python shell){
    print $subject,"\n";
}

其中$subject是控制變量,每一個迭代過程當中,都會從列表或數組中取出一個元素賦值給控制變量。

迭代數組:

@arr=qw(perl python shell);
foreach $subject (@arr){
    print $subject,"\n";
}

迭代過程當中,賦值給控制變量的實際上是列表或數組中的引用,並不是是直接取出元素的值賦值給控制變量的(也就是說,不是變量複製)。所以,在foreach過程當中修改控制變量的值也會修改列表/數組中元素的值

@arr=qw(perl python shell);
foreach $subject (@arr) {
    $subject .= "aaa";
}
print @arr;         # 輸出perlaaapythonaaashellaaa

當foreach遍歷結束後,控制變量將復原爲foreach遍歷前的值(例如未定義的是undef)。

$subject="php";
foreach $subject (qw(perl python shell)){
}
print $subject;     # 輸出"php"

默認變量$_

在foreach遍歷結構中也能夠省略控制變量部分,這時會使用默認的變量$_做爲控制變量,每次迭代都會從數組中取出一個列表/數組的索引賦值給$_

foreach (qw(perl python shell)) {
    print $_,"\n";
}

其實,perl中不少地方沒有"需求數據"時,都會自動使用$_。例以下面的print函數就使用了$_

$_="hello world!\n";
print;

sort()和reverse()

  • sort()用於對列表/數組進行升序排序,默認按照unicode(包含ascii)順序:數字<大寫字母<小寫字母。在之後,還能夠自定義排序規則。
  • reverse()則是對列表/數組的當前順序進行反轉。
  • sort()和reverse()的排序/反轉的效果是體如今返回值中的,它不會改變原始列表/數組中元素的順序。
print reverse 11,6..8,20,"\n";    # 輸出順序:20 8 7 6 11

@arr=qw(perl python shell);
reverse @arr;            # 反轉了順序,但返回結果丟棄了,@arr不變
print @arr,"\n";         # 返回順序:perl python shell

@arr1=reverse @arr;      # @arr1中元素的順序:shell python perl
print '@arr1: ',@arr1,"\n";

@sort_arr=sort @arr;     # 排序,但由於@arr中元素順序本就是升序的
print '@sort_arr: ',@sort_arr,"\n";  # 返回順序:perl python shell

sort @arr;               # 雖排序,但丟棄了排序結果

each()

each操做符能夠獲取一個鍵值對(key/value)。能夠操做數組,也能夠操做hash。each操做hash的內容見後文。

each對數組操做時,返回的是數組中元素的索引號和該元素的值。

my @arr=qw(perl python shell);
while (my($index,$value) = each(@arr)){
    print "$index: $value","\n";
}

其中my關鍵字表示該變量是局部變量。如下是執行結果:

0: perl
1: python
2: shell

若是不使用each,則須要遍歷數組,並獲取數組的索引以及元素的值。

@arr=qw(perl python shell);
foreach $index (0..$#{arr}) {
    print "$index: $arr[$index]","\n";
}
相關文章
相關標籤/搜索