Вопрос по perl – Безопасно ли в Perl удалять ключ из ссылки на хеш, когда я зацикливаюсь на том же хеше? И почему?

10

Я в основном хочу сделать это:

foreach my $key (keys $hash_ref) {

    Do stuff with my $key and $hash_ref

    # Delete the key from the hash
    delete $hash_ref->{$key};
}

Это безопасно? И почему?

Ваш Ответ

2   ответа
3

keys %hash предоставляет весь список один раз, прежде чем начать итерацию.foreach затем продолжает работать с этим предварительно сгенерированным списком, независимо от того, что вы изменяете внутри фактического хэша.

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

17

keys до того, как вы начали зацикливаться. Имейте в виду, что

for my $key (keys %$hash_ref) {
   ...
}

примерно так же, как

my @anon = keys %$hash_ref;
for my $key (@anon) {
   ...
}

Удаление из хеша не вызывает никаких проблем.

eachс другой стороны, перебирает хеш. Каждый раз, когда это называется,each возвращает другой элемент. Тем не менее, это все еще безопасно дляdelete текущий элемент!

# Also safe
while (my ($key) = each(%$hash_ref)) {
   ...
   delete $hash_ref->{$key};
   ...
}

If you add or delete a hash's elements while iterating over it, entries may be skipped or duplicated--so don't do that. Exception: It is always safe to delete the item most recently returned by each()

ах. добавлено вperl5.git.perl.org/perl.git/commit/…удалено вperl5.git.perl.org/perl.git/commit/…
кто добавил это "в текущей реализации"? это не всегда было там, и не должно быть там сейчас, если нет действительно очень веской причины. Обновление: кажется, там больше нет.
@LeoNerd, более старый Perl (по крайней мере, 5.10), просто скажите "Удалить всегда безопасно ..." По очевидным причинам совместимости, я сомневаюсь, что это когда-либо будет изменено без введения некоторыхuse feature или другая подобная прагма.
Формулировка «в текущей реализации» меня немного пугает, потому что, похоже, там есть место, чтобы изменить реализацию так, чтобы она больше не была безопасной. Я не буду полагаться на это, но тогда я не буду использоватьeach() либо - foreach ключи в порядке.

Похожие вопросы