2013-07-10 11 views
2

В perl 5.10.1 можно ли добавлять новые элементы в хэш, итерации через него с помощью оператора each?Добавление новых членов при итерации хэша с «каждым»

Smth. как в этом коде (подготовка данных для диаграмм 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; 
} 
+0

Спасибо! Можно ли опустить '@ keys' в свой код и просто использовать' для my $ k (keys% hash) '? –

+1

@AlexanderFarber Да, в этом случае '@ keys' могут быть опущены. Я использовал дополнительную переменную, чтобы сделать копирование списка ключей ясным. Однако нельзя использовать циклы foreach, если изменить массив, который выполняется итерацией. – amon

2

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

0

documentation for each() довольно ясно по этому вопросу.

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