1. 程式人生 > >Perl資料型別:列表與陣列

Perl資料型別:列表與陣列

列表與陣列

1. 列表和陣列的定義

  • 列表:指的是儲存列表的有序集合;(真實的資料)
  • 陣列:儲存列表的變數;(儲存列表的容器)
    • 對比與標量,列表對應於資料,陣列對應於變數;
  • 陣列和列表的特性:
    • 陣列和列表的每個元素都是單獨的標量變數,擁有獨立的標量值,這些值是有序的(順序固定);
    • 陣列和列表都有對應的整數作為索引,從0開始,依次遞增;
    • 陣列和列表的每個元素都都是獨立的,因此其型別可以不同(字串,數字等)<一般相同>;
    • 陣列和列表可以包含任意多個元素;
    • 使用@字元來宣告一個數組;

2. 陣列中的元素

  • 陣列元素呼叫方法:
#!/usr/bin/perl -w
$fred = 0;
$index = 2.345;
@fred = (yabba, dabba, doo);
print $fred;     #列印0
print $fred[0];  #print yabba
print $fred[$number - 1] ;  #print dabba (自動去除小數,無論正負)
print $fred[123];           #print undef

2.1 特殊的陣列索引

假如你對索引值超過陣列尾端的元素進行賦值,陣列將會根據需要自動增大–只要能分配可用的記憶體,perl的陣列可以無限大,見下例:

#special index
$rocks[0] = 'dedrock';  # 1 element
$rocks[1] = 'slate';    # 2 elements
$rocks[2] = 'lava';     # 3 elements
$rocks[3] = 'crushed';  # 4 elements
$rocks[99] = 'schist';  # 5 elements,and 95 undef elements
#last index of array
$end  = $#rocks;        # $end = 99, the last index of array
print $rocks[$#rocks]; # print "schist" #minus index (基本沒人使用除-1之外的負索引值) print $rocks[-1]; # print "schist" print $rocks[-100]; # print "dedrock" print $rocks[-2000]; # ERROR!

2.2 列表和陣列的賦值

  • 列表直接量:直接寫成資料形式的列表;
#normal list
(1,2,3)       #包含元素1,2,3
(1,2,3,)      #包含元素1,2,3,最後的逗號被忽略
("fred",4,5)  #包含元素“fred”,4,5
()            #不包含元素的空列表
(1..5)        #列表(1,2,3,4,5)
(5..1)        #空列表,只能向上計數
(0..$#rocks)  #列表中元素為,rocks陣列中的所有索引 
  • qw 簡寫
#qw style
("fred","barney","betty","wilma")    #包含四個元素的列表
qw(fred barney betty wilma)  #和上面列表相同
#除小括號外,也可以使用其他的定界符來幫助perl區分陣列列表的邊界
qw!fred barney betty wilma!  #和上面列表相同
qw/fred barney betty wilma/  #和上面列表相同
qw{fred barney betty wilma}  #和上面列表相同
qw[fred barney betty wilma]  #和上面列表相同
qw<fred barney betty wilma>  #和上面列表相同
#當列表中有某些字元的時候,使用其他的定界符便具有更大的優勢
qw {
    /usr/bin/perl
    /usr/rootbeer/test.pl
}
  • 列表的賦值
#列表賦值
($fred,$barny,$dino) = ("flintstone","rubble",undef);
($fred,$barney) = (1,2,3,4);    # 3 和 4 被丟棄
($fred,$barney) = (1);          # $dino的值為undef
($fred,$barney) = qw(1,2,3,4);  # 3 和 4 被丟棄
#列表在賦值之前建立,因此可以在perl交換兩個變數的值
($fred,$barney) = ($barney,$fred) ;
#當我們想引用整個陣列時,perl提供更簡便的用法:
@rocks = qw/bedrock slate lav/;   # 3個元素
@tiny = ();                       # 空列表
@giant = 1..1e5;                  # 100000個元素
@stuff = (@rocks,@tiny,@giant);   # 100003個元素,空列表不佔位置,不計數列表為:/bedrock slate lav 1 2 3 ... 1e5/

3. 陣列操作符

3.1 “pop” & “push” 操作符

  • pop 和 push 的第一個引數必須是陣列變數,對列表直接量進行push和pop是沒有意義的;
    • pop 取走陣列和列表末尾的元素,並以此為返回值;
    • push 將資料放入陣列和列表的末尾;
#pop operation
@array = 1..5;
$fred = pop (@array);   #$fred = 5
$fred = pop @array;     #$fred = 4
pop @array;             #@array = (1,2) now

#push operation
push @array,8;         #@array = (1,2,8) now
push (@array,8);       #@array = (1,2,8,8) now
push @array,1..5;      #@array = (1,2,8,8,1,2,3,4,5) now

3.2 “shift” & “unshift” 操作符

  • shift 和 unshift 的第一個引數必須是陣列變數,對列表直接量進行shift和unshift是沒有意義的;
    • shift 取走陣列和列表首部的元素,並以此為返回值;
    • unshift 將資料放入陣列和列表的首部;
#shift operation
@array = 1..5;
$fred = shift (@array);   #$fred = 1
$fred = shift @array;     #$fred = 2
shift @array;             #@array = (4,5) now
@array1 = ();
$array_shift = shift @array1; #$array_shift = undef;

#inshift operation
unshift @array,8;         #@array = (8,4,5) now
unshift (@array,8);       #@array = (8,8,4,5) now
unshift @array,1..5;      #@array = (1,2,3,4,5,8,8,4,5) now

3.3 “splice” 操作符

  • shift & unshift,pop & push都是針對陣列首尾元素操作的,而 “splice” 操作符用於運算元組中間的元素;
    • splice共有4個引數,其用法見下例:
#splice operation with 2 parameter
#第一個引數指定要操作的對陣列,第二個引數是要操作的元素的起始位置;
@array = 1..5;
@removed = splice @array,2;  #在原來的陣列中刪除從3往後的元素:@removed is (3,4,5) now @array is (1,2) now
#splice operation with 3 parameter
#第三個引數是要操作的元素的個數(不是結束位置)
@array = 1..5;
@removed = splice @array,2,2;  #在原來的陣列中刪除從3往後2個元素:@removed is (3,4) now @array is (1,2,5) now
@removed = splice @array,2,0;  #在原來的陣列中刪除從5往後0個元素:@removed is () now @array is (1,2,5) now
#splice operation with 4 parameter
#第四個引數是要替換的列表,在第二個引數位置插入替換列表,原列表中元素向後順移
@array = 1..5;
@removed = splice @array,2,2,(8,9);  #在原來的陣列中刪除從3往後2個元素,並插入新列表:@removed is (3,4) now @array is (1,2,8,9,5) now
@removed = splice @array,2,0,(5,5);  #在原來的陣列中刪除從8往後0個元素,並插入新列表:@removed is () now @array is (1,2,5,5,8,9,5) now

3.4 “sort” & “reverse” 操作符

  • sort 和 reverse 用於對陣列元素進行排序和倒序;
    • sort 依次按照字元內部的編碼數需對其進行排序;
      • 大寫字元在小寫字元前;
      • 數字排在字元之前;
      • 標點符號散落在各處;
    • reverse 將陣列進行完全倒序的排列;
#sort operation
@array = qw/abc guy alo pok/;
@sorted = sort (@array);    #@sorted is qw/abc alo guy pok/ now
@sorted_num = sort 99..103; #@sorted_num is qw/100 101 102 103 99/ now
#那麼如何使用perl對數字進行排序呢?
@sorted_num = sort { $a <=> $b } 99..103; #@sorted_num is qw/99 100 101 102 103/ now
@sorted_num = sort { $a cmp $b } 99..103; #@sorted_num is qw/100 101 102 103 99/ now

#reverse operation
@array = qw/abc guy alo pok/;
@sorted = sort (@array);         #@sorted is qw/abc alo guy pok/ now
@reversed = reverse sort @array; #@revered is qw/pok guy alo abc/ now

3.5 字串中的陣列內插

  • 和標量一樣,陣列也可以內插到雙引號的字串內。內插時,會在陣列的各個元素之間自動新增分割用的空格。
#陣列內插
@array = qw/abc guy alo pok/;
print "rocks @array end.\n"; #same as print "rocks abc guy alo pok end.\n"

# @ character print
$email = "[email protected]"; # 此時會呼叫@qq陣列 

#使用以下方法列印 @ 字元
print "fred\@qq.com";
print '[email protected]';

#內插陣列的某個元素
@fred = qw/hello world/;
$fred = "fred";
$y = 2;
$x = "this is $fred[1]'s place.";      # this is world's place.
$x = "this is ${fred}[1]'s place.";    # this is fred[1]'s place.

4. 陣列遍歷方法

4.1 foreach結構

  • 為了能夠處理perl中整個陣列或者列表的資料,perl提供foreach迴圈,他可以逐步遍歷列表中的值;
    • 每次迭代時,控制變數都會取得新值(如下例中的$rock,每次迴圈都取不同的值);
    • 控制變數並不是列表元素的複製,他就是列表元素本身。如果我們在迴圈中修改元素的值,也就修改了這個元素。
    • 當迴圈結束時,控制變數變回其初始值,如果最初未定義,變回undef;
#foreach syntax
foreach $rock (qw/bedrock slate lava/) {
	print "One rock is $rock.\n";     #第一次迴圈,rock -> bedrock, 第三次迴圈,rock -> lava
	# $rock .= "\n";                  #如果採用此行,在每個列表元素後面加上換行符
}

4.2 ecah操作符

  • each操作符時v5.12以後增加的操作符;
    • 在此之前,each只能用於讀取雜湊的key-value對;
    • 每次呼叫,each會返回下一個元素的兩個引數:陣列索引 + 元素值;
#each syntax
use v5.12$rocks = qw/bedrock slate lava/; 
while (($index,$value) = each @rocks) {
	print "$index: $value.\n"; 
}

#也可以用foreach來實現列印整個陣列
foreach $index (0..$#rocks) {
	print "$index: $rocks[$index].\n";
}

4.3 Perl最喜歡的預設變數“$_”

  • 如果在foreach中未定義控制變數,那麼系統預設採用$_變數
    • Perl有許多預設變數,這是最常用的一個;
# $_ character
#ex_1
$_ = "Yaha dabba doo.\n";
print ;  #預設列印$_
#ex_2
foreach (qw/bedrock slate lava/) {
	print "One rock is $_.\n";     #第一次迴圈,rock -> bedrock, 第三次迴圈,rock -> lava
	# $_ .= "\n";                  #如果採用此行,在每個列表元素後面加上換行符
}

5. 標量上下文和列表上下文

5.1 上下文的定義

  • 上下文:指的是如何使用表示式;
    • 使用數字操作符時的結果就是數字;
    • 使用字串操作符的結果就是字串;
    • perl在解析表示式時,要麼希望得到標量,要麼希望得到列表;
#陣列名稱在上下文中的不同返回結果
@people = qw/fred bob betty/;
@sorted = sort @people;    #@sorted is qw/betty bob fred/  now
$number = @people;         #$number is 3, return the array size

5.2 標量上下文中使用產生列表的表示式

#list in scalar
@people = qw/fred bob betty/;
@sorted = reverse @people;     #@sorted is qw/betty bob fred/  now  #列表上下文
$number = reverse @people;     #$number is "yttebbobderf"           #標量上下文
$number = something;        #標量上下文
@number = something;        #列表上下文
($fred,$betty) = something; #列表上下文
($fred) = something;        #列表上下文
print something;           #列表上下文
#強行引入標量上下文scalar(沒有強制引入列表的上下文,因為根本不需要)
print "there are", scalar @people, "person in array \@people.\n";

5.3 列表上下文中使用產生標量的表示式

#scalar in list
@people = 2 * 8;  #得到單個元素的列表(42)
@wilma = undef;   #不會得到空陣列,而會得到一個元素的陣列,內含一個空元素

5.4 列表上下文中的<STDIN>

  • 標量上下文中,<STDIN>返回的是輸入資料的下一行內容;
  • 列表上下文中,<STDIN>返回的是所有剩下行的內容;
    • 列表上下文中,如何規定檔案或者輸入資料來源結束呢?
    • Unix:Ctrl+D
    • Window: Ctrl+Z
#<STDIN> in list
@lines = <STDIN>;          #一次讀取所有行的內容;
chomp(@lines);             #去除讀入的所有行的換行符;
chomp(@lines = <STDIN>);   #一次讀取所有行的內容,去除所有行的換行符;(更簡潔的寫法)