while (my ($k,$v) = first %hash) { delete $hash{$_} for $k, @$v; } #### use strict; use warnings; use feature 'say'; use Data::Dump qw( pp ); sub first (\%) { my $hash = shift; scalar(keys %$hash); # Force reset each %$hash; } my %hash = ( 1 => [2..7], 8 => [ 9 ], 9 => [ 8 ], (map { $_ => [ 1 ] } 2..7), ); say "Input hash:", pp \%hash; say ""; say "Try first then each twice in a row to check that the iteration is restarted"; say pp [first %hash], [each %hash] for 1..2; say ""; # Delete a key and all the keys contained in the value array sub rec_delete(\%$); sub rec_delete(\%$) { my ($hash, $key) = @_; my $array = delete $hash->{$key}; return unless $array; say " Removing $key -> [ @$array ]"; rec_delete %$hash => $_ for @$array; } while (my ($k,$v) = first %hash) { say "Starting from $k -> [ @$v ]"; rec_delete %hash => $k; } #### Input hash:{ 1 => [2 .. 7], 2 => [1], 3 => [1], 4 => [1], 5 => [1], 6 => [1], 7 => [1], 8 => [9], 9 => [8] } Try first then each twice in a row to check that the iteration is restarted ([8, [9]], [5, [1]]) ([8, [9]], [5, [1]]) Starting from 8 -> [ 9 ] Removing 8 -> [ 9 ] Removing 9 -> [ 8 ] Starting from 5 -> [ 1 ] Removing 5 -> [ 1 ] Removing 1 -> [ 2 3 4 5 6 7 ] Removing 2 -> [ 1 ] Removing 3 -> [ 1 ] Removing 4 -> [ 1 ] Removing 6 -> [ 1 ] Removing 7 -> [ 1 ] #### While the hash isn't empty Take one key (at random) from the hash Delete that key and all connected keys