Добавление новых членов при повторении хэша с "каждым"

В perl 5.10.1 нормально ли добавлять новые члены в хеш, перебирая его с помощью each оператор?

Что-л. как в этом коде (подготовка данных для диаграмм Google), где у меня есть хэш хэшей массивов, и я пытаюсь переместить последний элемент каждого массива:

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

}

3 ответа

Решение

Обычно небезопасно добавлять или удалять записи хеша при его повторении с использованием each, Если вы хотите сделать это, лучше всего сохранить явный список ключей, которые вы хотите перебрать в массив, и выполнить цикл по нему.

Вместо

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

делать

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

Это не безопасно. Если вы сделаете это, вы получите предупреждение: "Использование each() для хеша после вставки без сброса итератора хеша приводит к неопределенному поведению".

Документация дляeach() довольно ясно об этом.

Если вы добавляете или удаляете элементы хэша во время итерации по нему, вы можете пропустить или дублировать записи, так что не делайте этого.

Другие вопросы по тегам