Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re^3: Iterating over hash while deleting elements

by Eily (Monsignor)
on Feb 06, 2020 at 17:07 UTC ( [id://11112504]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Iterating over hash while deleting elements
in thread Iterating over an hash while removing keys

Oh I didn't mean I don't trust perl with that. It's whoever is using perl I have trust issues against ;-)

Replies are listed 'Best First'.
Re^4: Iterating over hash while deleting elements
by LanX (Saint) on Feb 06, 2020 at 17:21 UTC
    point is you must delete the current key to avoid an endless loop.

    not sure how an idiot proof algo would look like.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      I guess then:

      sub delete_first(\%) { my $hash = shift; keys %$hash; my ($key, $value) = each %$hash; delete $hash->{$key}; wantarray ? ($key, $value) : $key; } while (my $key = delete_first %hash) { do_stuff(); }
      Would be safer. At least delete_first doesn't depend on the current state of the hash's iterator, and the iterator (each) is still valid right after calling it.

        > while (my $key = delete_first %hash)

        I don't think a new iterator is the best generic approach.

        Because only the loop's body knows if resetting the iterator is appropriate.

        for the general case - iterating a hash and occasionally deleting elements in the body, this should always fit

        while (my $key = each %hash) { if ( condition($key) ) { delete @hash{ dependent_keys($key) }; keys %hash; } }

        The Rule: reset the iterator if and only if other elements are deleted.

        This will never end in an endless loop, because the hash will

        • either be emptied ²
        • or the last "re-iteration" is not interrupted.
        The only difficulty might be efficiency consideration:
        • If the $key itself is deleted
          => this should be done outside the if-block to not reset °
        • If the $key itself is NOT deleted
          => you might want to avoid processing it again by a checking a %seen hash.
        my %seen; while (my $key = each %hash) { next if $seen{$key}++; if ( condition($key) ) { delete @hash{ dependent_keys($key) }; keys %hash; } }

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        °) not sure how costly resetting is in the end.

        ²) provided it's a finite structure which isn't refilled simultanously

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11112504]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (2)
As of 2024-03-19 06:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found