Quy tắc chung là sử dụng chức năng phù hợp nhất với nhu cầu của bạn.
Nếu bạn chỉ muốn các phím và không có kế hoạch từng đọc bất kỳ giá trị, sử dụng các phím():
foreach my $key (keys %hash) { ... }
Nếu bạn chỉ muốn các giá trị, giá trị sử dụng():
foreach my $val (values %hash) { ... }
Nếu bạn cần các phím và các giá trị, sử dụng mỗi():
keys %hash; # reset the internal iterator so a prior each() doesn't affect the loop
while(my($k, $v) = each %hash) { ... }
Nếu bạn định thay đổi các khóa của băm theo bất kỳ cách nào trừ để xóa khóa hiện tại trong khi lặp lại, thì bạn không được sử dụng từng(). Ví dụ, đoạn mã này để tạo ra một bộ mới của các phím chữ hoa với giá trị tăng gấp đôi hoạt động tốt sử dụng các phím():
%h = (a => 1, b => 2);
foreach my $k (keys %h)
{
$h{uc $k} = $h{$k} * 2;
}
sản xuất dự kiến băm kết quả:
(a => 1, A => 2, b => 2, B => 4)
Nhưng sử dụng mỗi() để thực hiện cùng một điều:
%h = (a => 1, b => 2);
keys %h;
while(my($k, $v) = each %h)
{
$h{uc $k} = $h{$k} * 2; # BAD IDEA!
}
tạo kết quả không chính xác theo cách khó dự đoán.Ví dụ:
(a => 1, A => 2, b => 2, B => 8)
này, tuy nhiên, là an toàn:
keys %h;
while(my($k, $v) = each %h)
{
if(...)
{
delete $h{$k}; # This is safe
}
}
Tất cả điều này được mô tả trong tài liệu perl:
% perldoc -f keys
% perldoc -f each
Vui lòng thêm một khóa void-context% h; trước mỗi vòng lặp để hiển thị một cách an toàn bằng cách sử dụng trình lặp. – ysth
Có một cảnh báo trước khác. Trình lặp được ràng buộc với hàm băm, không phải là bối cảnh, có nghĩa là nó không được tái nhập. Ví dụ, nếu bạn lặp qua một băm, và in giá trị băm perl sẽ thiết lập lại bộ lặp, làm cho mã này lặp vô tận: % băm của tôi = (a => 1, b => 2, c => 3,); trong khi (của tôi ($ k, $ v) = mỗi băm%) { in% băm; } Đọc thêm tại http://blogs.perl.org/users/rurban/2014/04/do-not-use-each.html – Rawler