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
顯然,第一次遍歷儘管用了塊作用域,但仍然影響了第二次遍歷的結果。