Question

In perl 5.10.1 is it ok to add new members to a hash while iterating through it with the each operator?

Smth. like in this code (preparing data for Google charts), where I have a hash of hashes of arrays and I am trying to move the last element of each array:

sub split_aclr($) {
        my $csvData = shift;

        while (my ($csv, $href) = each %$csvData) {
                next unless $csv =~ /_ACLR_/i;
                my $len = scalar @{$href->{MEASUREMENT}};

                if ($len > 1 && $href->{MEASUREMENT}->[$len - 1] eq 'CARRIER_CHANNEL') {
                        while (my ($key, $arr) = each %$href) {
                                my $moved = pop @$arr;
                                $csvData{$csv . '_CARRIER_CHANNEL'} = {$key => [ $moved ]};
                        }
                }
        }

}

Was it helpful?

Solution

It is not generally safe to add or remove entries of a hash while iterating it using each. If you want to do so, it might be best to save an explicit list of keys you want to iterate to an array, and loop over that.

Instead of

while (my $k, $v) = each %hash) {
  $hash{"foo_$k"} = $v;
}

do

my @keys = keys %hash;
for my $k (@keys) {
  my $v = $hash{$k};
  $hash{"foo_$k"} = $v;
}

OTHER TIPS

It isn't safe. If you do it, you will get a warning: "Use of each() on hash after insertion without resetting hash iterator results in undefined behavior."

The documentation for each() is pretty clear on this.

If you add or delete elements of a hash while you're iterating over it, you may get entries skipped or duplicated, so don't.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top