我使用each
通過一個Perl哈希迭代:我可以在不重置其「每個」迭代器的情況下複製散列嗎?
while (my ($key,$val) = each %hash) {
...
}
然後一些有趣的情況,我想打印出來的哈希值。起初,我認爲是這樣的:
while (my ($key,$val) = each %hash) {
if (something_interesting_happens()) {
foreach my $k (keys %hash) { print "$k => $hash{$k}\n" }
}
}
但是,這是行不通的,因爲大家都知道,一個散列調用keys
(或values
)重置用於each
內部迭代器,我們可以得到一個無限循環。例如,這些腳本將永遠運行:
perl -e '%a=(foo=>1); while(each %a){keys %a}'
perl -e '%a=(foo=>1); while(each %a){values %a}'
沒問題,我想。我可以製作哈希的副本,並打印出副本。
if (something_interesting_happens()) {
%hash2 = %hash;
foreach my $k (keys %hash2) { print "$k => $hash2{$k}\n" }
}
但這也行不通。這也會重置迭代器each
。實際上,在列表上下文中使用%hash
似乎會重置其迭代器each
。所以這些也永遠運行:
perl -e '%a=(foo=>1); while(each %a){%b = %a}'
perl -e '%a=(foo=>1); while(each %a){@b = %a}'
perl -e '%a=(foo=>1); while(each %a){print %a}'
這是記錄在任何地方嗎?有意義的是,perl可能需要使用相同的內部迭代器來將哈希的內容推送到返回棧中,但我也可以想象不需要這樣做的哈希實現。
更重要的是,有沒有辦法做我想要的?在不重置迭代器的情況下獲得散列的所有元素?
這也表明你不能在each
迭代中調試散列。考慮上運行的調試器:
%a = (foo => 123, bar => 456);
while (($k,$v) = each %a) {
$DB::single = 1;
$o .= "$k,$v;";
}
print $o;
只需通過檢查,其中調試器停止(比如打字p %a
或x %a
)哈希,你會改變程序的輸出。
更新:我上傳Hash::SafeKeys
作爲一般的解決這個問題。感謝@gpojd指導我正確的方向,@cjm提供了一個讓解決方案更簡單的建議。
最近遇到同樣的問題。發現Hash :: SafeKeys非常慢並且依賴於散列大小,並且Hash :: StoredIterator +默認鍵的性能要好得多。 –
@AlexandrEvstigneev - 謝謝你,這很有趣。我會對'Hash :: SafeKeys'進行一些更新' – mob