陣列 (Array) 和串列 (List)

    前言

    Perl 的陣列 (array) 是一種線性的容器,以數字做為索引,可儲存異質資料。串列則是一序列的資料。這兩者有一些關連,本文介紹 Perl 陣列和串列。

    陣列 (Array) vs 串列 (List)

    在 Perl 裡面,陣列和串列不完全相同,如 push 函式的宣告:

    push ARRAY, LIST
    

    push 會把串列加入陣列尾端,由此可知,Perl 對陣列和串列的看法有差異。

    我們看一下以下的程式碼片段:

    my @arr = ("foo", "bar", "baz");
    

    在這個程式碼中,@arr 是陣列,而 ("foo", "bar", "baz") 是串列。由此可知,陣列是儲存串列的變數,串列是一個序列的資料。

    建立陣列

    以下程式碼片段用空串列建立空陣列:

    my $arr = ();
    

    以下程式碼片段用現有的串列建立陣列:

    my @arr = ("foo", "bar", "baz");
    

    以下程式碼片段用現有的陣列建立新陣列:

    my @a = (1, 2, 3);
    my @b = (10, @a, 11);
    

    這時候 @a 會自動攤平 (flatten),@b 會是 (10, 1, 2, 3, 11)

    以索引 (index) 存取陣列

    存取陣列元素時,以數字為索引 (index),從零開始計數 (zero-based)。如下例:

    my @arr = ("foo", "bar", "baz");
    
    $arr[0] == "foo" or die "Wrong value";
    $arr[1] == "bar" or die "Wrong value";
    $arr[2] == "baz" or die "Wrong value";
    

    要注意,我們一開始宣告 @arr 時,其 sigil 是 @,但我們以 $arr[0] 取索引時,其 sigil 是 $。Perl 針對不同類型的變數會使用不同的 sigil,一開始容易寫錯,需注意。

    取得陣列長度

    使用 scalar 函式可取得陣列長度,如下例:

    my @a = (1, 2, 3);
    my @b = (10, @a, 11);
    
    scalar(@a) == 3 or die "Wrong length";
    scalar(@b) == 5 or die "Wrong length";
    

    Perl 另外有一個 length 函式,該函式用來取得字串長度,而非陣列長度。

    scalar 其實牽涉到語境 (context) 的概念,我們留在後文介紹。

    取得陣列尾端的索引

    使用 $# 搭配陣列變數可取得尾端的索引值。參考下例:

    my @arr = (1, 2, 3, 4, 5);
    
    $#arr == 4 or die "Wrong index";
    

    修改 $# sigil 所指向的變數會改變陣列的長度,故不建議這麼做。

    走訪陣列

    使用 for 迴圈搭配計數器可走訪陣列:

    my @arr = ("foo", "bar", "baz", "qux");
    
    for (my $i = 0; $i < scalar(@arr); $i++) {
        print $arr[$i], "\n";
    }
    

    如果不需計數器,也可以直接走訪串列:

    my @arr = ("foo", "bar", "baz", "qux");
    
    for my $e (@arr) {
        print $e, "\n";
    }
    

    在此處,for 可使用陣列或串列來走訪,皆視為串列。

    清空陣列

    對陣列指派空串列可清空原有的陣列,如下例:

    @arr = ();
    

    操作陣列的函式

    Perl 內建一些操作陣列的函式,可用來搬移資料。

    push

    push 會將額外的元素加入陣列尾端,如下例:

    my @arr = ("foo", "bar");
    
    push @arr, "baz", "qux", "quux";
    scalar(@arr) == 5 or die "Wrong length";
    $arr[2] == "baz" or die "Wrong value";
    $arr[4] == "quux" or die "Wrong value";
    

    pop

    pop 會從陣列尾端移除一個元素,如下例:

    my @arr = ("foo", "bar", "baz");
    
    my $popped = pop @arr;
    $popped == "baz" or die "Wrong value";
    scalar(@arr) == 2 or die "Wrong length";
    

    unshift

    unshift 會將元素放入陣列頭端,如下例:

    my @arr = ("foo", "bar");
    
    unshift @arr, "baz", "qux", "quux";
    scalar(@arr) == 5 or die "Wrong length";
    $arr[0] == "baz" or die "Wrong value";
    $arr[1] == "qux" or die "Wrong value";
    $arr[2] == "quux" or die "Wrong value";
    

    shift

    shift 會從陣列頭端移除一個元素,如下例:

    my @arr = ("foo", "bar", "baz");
    
    my $shifted = shift @arr;
    $shifted == "foo" or die "Wrong value";
    scalar(@arr) == 2 or die "Wrong length";
    

    splice

    splice 會在陣列中任一位置插入元素,其宣告如下:

    splice ARRAY,OFFSET,LENGTH,LIST
    splice ARRAY,OFFSET,LENGTH
    splice ARRAY,OFFSET
    splice ARRAY
    

    由此宣告可知,splice 有四個使用情境:

    • splice ARRAY,OFFSET,LENGTH,LIST:在 OFFSET 處,移除長度為 LENGTH 的元素後,插入 LIST
    • splice ARRAY,OFFSET,LENGTH:在 OFFSET 處,移除長度為 LENGTH 的元素
    • splice ARRAY,OFFSET:移除 OFFSET 後所有的元素
    • splice ARRAY:移除所有元素

    以下是實例:

    my @arr = ("foo", "bar", "baz", "qux");
    
    my $shifted = splice @arr, 1, 2, "quux";
    scalar(@arr) == 3 or die "Wrong length";
    $arr[1] == "quux" or die "Wrong value";
    

    陣列和串列的解構運算

    我們可以將串列指派到另一個串列:

    my ($a, $b, $c) = (1, 2, 3);
    
    $a == 1 or die "Wrong value";
    $b == 2 or die "Wrong value";
    $c == 3 or die "Wrong value";
    

    若右方串列過長,多餘的值會自動拋棄:

    my ($a, $b, $c) = (1, 2, 3, 4, 5);
    

    若左方串列過長,多餘的變數會變成未定義:

    my ($a, $b, $c) = (1, 2);
    
    !defined($c) or die "Wrong value";
    

    也可以將串列指派到陣列:

    my ($a, $b, @arr) = (1, 2, 3, 4, 5);
    
    scalar(@arr) == 3 or die "Wrong length";
    $arr[0] == 3 or die "Wrong value";
    $arr[1] == 4 or die "Wrong value";
    $arr[2] == 5 or die "Wrong value";
    

    這時候 @arr 會接收右方剩餘的串列元素,故為 (3, 4, 5)

    還可以將陣列拆開:

    my ($a, $b, $c) = @arr;
    

    這時候 $a$b$c 分別會指派為 @arr 的第一、第二、第三個值。

    【分享本文】
    Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Yahoo
    【追蹤本站】
    Facebook Facebook Twitter Parler