Perl中的each方法

    each函數用以一次一個鍵字/數值對的方式遍歷一個散列。

    在散列內部,它以一種看上去是隨機的順序維護它自己的記錄。each 可以遍歷這個序列是因爲每個散列都記得上一次返回的是哪條記錄。這個序列的實際的順序可能在將來的 Perl 版本里會改變,但有一點可以保證,就是 keys(或者 values)函數在同一個(未修改)的散列上生成的順序是一樣的。
    每個散列都有一個遍歷器,由在該程序裏所有的 each,keys,和 values 函數調用共享;該遍歷器可以通過從散列裏讀取所有元素來重置,或者通過計算 keys %hash 或 values %hash 來重置。如果你在遍歷散列的過程中刪除了元素,那麼後果還沒有很好的定義:記錄可能會被忽略也可能被重複。

    因爲each函數每次只返回一對鍵值而不是返回整個列表,所以必須記錄上一次的訪問位置。
    關於遍歷器對位置的記錄,見下面示例:

    #!/usr/bin/perl -w
    ##############################
    use strict;
    my %hash = ( 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6,);
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
        last if($k eq "3");
    }
    print "----------------------\n";
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
    }


    執行代碼,輸出如下:

    $ ./test.pl 
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    ----------------------
    2  =>  2
    5  =>  5


  顯然,each函數的內部遍歷器記錄了上次遍歷的位置,第二次遍歷時從前一次的位置開始。

  如果第一次遍歷到哈希尾部,則下次開始時會從首部開始遍歷:

    #!/usr/bin/perl -w
    ##############################
    use strict;
    my %hash = ( 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6,);
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
    }
    print "----------------------\n";
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
    }


  輸出如下:

    $ ./test.pl 
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    2  =>  2
    5  =>  5
    ----------------------
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    2  =>  2
    5  =>  5


如果第一次遍歷並沒有到達尾部,但使用 keys 重置一次遍歷器,下次也會從開頭開始遍歷,如下:

    #!/usr/bin/perl -w
    ##############################
    use strict;
    my %hash = ( 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6,);
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
        last if($k eq "3");
    }
    print "----------------------\n";
    keys %hash;
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
    }


  輸出:

    $ ./test.pl 
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    ----------------------
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    2  =>  2
    5  =>  5


  這裏的遍歷器記錄的是哈希本身的遍歷位置,而不是變量或引用名稱,如:

    #!/usr/bin/perl -w
    ##############################
    use strict;
    my %hash2 = ( x => { 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, });
    while(my ($K, $V) = each(%hash2)){
        while(my ($k, $v) = each(%$V)){
            print "$k  =>  $v\n";
            last if($k eq "3");
        }
    }    
    print "----------------------\n";
    while(my ($K, $V) = each(%hash2)){
        while(my ($k, $v) = each(%$V)){
            print "$k  =>  $v\n";
        }
    } 


  輸出如下:

    $ ./test.pl 
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    ----------------------
    2  =>  2
    5  =>  5


顯然,這裏的遍歷二級子哈希時使用了臨時變量,但Perl仍然記錄了變量的訪問位置。

而且,Perl的內部遍歷器是全局生效的,而不是像變量名那樣只在塊作用域中生效。

    #!/usr/bin/perl -w
    ##############################
    use strict;
    my %hash = ( 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6,);
    if(1){
        while(my ($k, $v) = each(%hash)){
            print "$k  =>  $v\n";
            last if($k eq "3");
        }
    }
    print "----------------------\n";
    while(my ($k, $v) = each(%hash)){
        print "$k  =>  $v\n";
    }


輸出:

    $ ./test.pl 
    6  =>  6
    4  =>  4
    1  =>  1
    3  =>  3
    ----------------------
    2  =>  2
    5  =>  5


顯然,第一次遍歷儘管用了塊作用域,但仍然影響了第二次遍歷的結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章