As saouq correctly points out there is no difference between:
for my $key (keys %my_hash) {
and
for my $key (my @temp = keys %my_hash) {
Both create a temporary list. Both will be unaffected by changes to %my_hash.
If you want to make sure you cover keys added in the loop processing, and skip keys deleted by the loop processing, then you'll need to do something messy like:
my %hash = (a => 1, b => 2); my %seen_key = (); my $seen_key_count; do { $seen_key_count = keys %seen_key; foreach my $key (keys %hash) { # skip any entries deleted since we called keys next unless exists $hash{$key}; # skip any keys we have already seen next if $seen_key{$key}++; my $value = $hash{$key}; # do stuff with $value print "$key = $value\n"; # and mangle the hash $hash{c}="foo"; delete $hash{b}; }; } until ($seen_key_count == keys %seen_key);
But I'd agree with jarich and dragonchild. This smells like a design problem. If I needed to code anything like this I would have a very strong suspicion that there was something seriously wrong somewhere in the codebase. Rather than fix the symptom I would try and track down and eliminate the disease.
Could you give more of a description why this is necessary? Perhaps we could suggest an alternative solution.
In reply to Re: Iterating hashes safely and efficiently
by adrianh
in thread Iterating hashes safely and efficiently
by rinceWind
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |