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

Re: Iterating over an hash while removing keys

by haukex (Chancellor)
on Feb 06, 2020 at 18:35 UTC ( #11112513=note: print w/replies, xml ) Need Help??


in reply to Iterating over an hash while removing keys

let's pretend there's an awful lot of them, or the hash is tied, and it's harder to find an existing key than fetch a value

Well, a pretty foolproof method is to build an array of keys to delete, and delete them later. But by what you said I am guessing this list might grow very long, so that might not be feasible?

LanX has a point that resetting the iterator on each loop might result in an endless loop if one is not careful. But I think that resetting the iterator only when keys are actually deleted might be an option, e.g.:

use warnings; use strict; use Data::Dump qw/ dd pp /; my %h = ( 1 => [2..7], 8 => [ 9 ], 9 => [ 8 ], (map { $_ => [ 1 ] } 2..7), ); dd \%h; while ( my ($k,$v) = each %h ) { print "Loop from ",pp($k)," -> ",pp($v),"\n"; rec_delete( \%h, $k ); } dd \%h; sub rec_delete { my ($hash, $key) = @_; return unless exists $hash->{$key}; my $value = delete $hash->{$key}; keys %$hash; return unless $value; print "Recursing ",pp($key)," -> ",pp($value),"\n"; rec_delete( $hash, $_ ) for @$value; }

Replies are listed 'Best First'.
Re^2: Iterating over an hash while removing keys
by Eily (Monsignor) on Feb 07, 2020 at 09:02 UTC

    Well, a pretty foolproof method is to build an array of keys to delete, and delete them later.
    An array of the initial keys would work. But with the cyclic nature of my data, trying to recurse and push new keys without deleting the ones that have already been processed would be an infinite loop. I could keep a hash of the keys that I want to delete I suppose...

    For the same reason, the fact that first() resets the iterator wouldn't even get the chance to be an issue, because if I didn't delete a key as I got it, the loop wouldn't even finish its first iteration. But LanX's answer and input from choroba did lead me to write this version of the fonction which is saner: it removes the key it returns, so the next call won't return it again.

Re^2: Iterating over an hash while removing keys
by Anonymous Monk on Feb 06, 2020 at 21:47 UTC
    That is certainly what I would do in this case. And, if the size of the list becomes a problem, just have it break out of the first loop, get rid of the keys it's found so far, and start over.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (6)
As of 2020-06-01 06:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?