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);