Is it safe in Perl to delete a key from a hash ref

2019-02-21 13:04发布

问题:

I basically want to do this:

foreach my $key (keys $hash_ref) {

    Do stuff with my $key and $hash_ref

    # Delete the key from the hash
    delete $hash_ref->{$key};
}

Is it safe? And why?

回答1:

You're not iterating over the hash, you're iterating over the list of keys returned by keys before you even started looping. Keep in mind that

for my $key (keys %$hash_ref) {
   ...
}

is roughly the same as

my @anon = keys %$hash_ref;
for my $key (@anon) {
   ...
}

Deleting from the hash causes no problem whatsoever.


each, on the other, does iterate over a hash. Each time it's called, each returns a different element. Yet, it's still safe to delete the current element!

# Also safe
while (my ($key) = each(%$hash_ref)) {
   ...
   delete $hash_ref->{$key};
   ...
}

If you add or delete a hash's elements while iterating over it, entries may be skipped or duplicated--so don't do that. Exception: It is always safe to delete the item most recently returned by each()



回答2:

It is safe, because keys %hash provides entire list once, before you start iterating. foreach then continues to work on this pre-generated list, no matter what you change inside actual hash.

It eats up your memory though, because you keep entire list until you've done.



标签: perl hash key