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

Можно ли в 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 ]};
                        }
                }
        }

}


person Alexander Farber    schedule 10.07.2013    source источник


Ответы (3)


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

Вместо

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;
}
person amon    schedule 10.07.2013
comment
Спасибо! Можно ли опустить @keys в коде и использовать только for my $k (keys %hash) ? - person Alexander Farber; 10.07.2013
comment
@AlexanderFarber Да, в этом случае @keys можно опустить. Я использовал дополнительную переменную, чтобы сделать копирование списка ключей понятным. Однако нельзя использовать циклы foreach, если нужно изменить итерируемый массив. - person amon; 10.07.2013

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

person Miguel Prz    schedule 10.07.2013

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

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

person Dave Cross    schedule 11.07.2013