hashperlperl5.10

Adding new members while iterating a hash with "each"


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 ]};
                        }
                }
        }

}


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