Безопасный способ удалить элементы из списка в Perl? - PullRequest
0 голосов
/ 01 ноября 2010

У меня странные результаты из этого perl-кода - мне нужно удалить несколько элементов из списка объектов Association.

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

Есть идеи, как этого избежать?Большое спасибо.

my @agentConfAssociationDeletionsList = (
    "AcceptTPCookie",
    "AgentNamesAreFQHostNames",
    "BadCssChars",
    "LogLocalTime"
);

#find associations to remove
my @associationsToRemove = ();
foreach my $association ($agentConf->GetAssociations()) {
    if ( grep {$_ eq $association->Name()} @agentConfAssociationDeletionsList) {
        print "pushing " . $association->Name() . "\n";
        push(@associationsToRemove, $association);
    }
}

#remove them
foreach my $association (@associationsToRemove) {
    print "removing association: " . $association->Name();
    agentConf->RemoveAssociation($association);
}

Ответы [ 4 ]

3 голосов
/ 01 ноября 2010

Ваш первый цикл такой:

my @associationsToRemove = ();
foreach my $association ($agentConf->GetAssociations()) {
    if ( grep {$_ eq $association->Name()} @agentConfAssociationDeletionsList) {
        print "pushing " . $association->Name() . "\n"; 
        push(@associationsToRemove, $association);  
    }
}

что эквивалентно этому:

my @associationsToRemove = ();
my @associations = $agentConf->GetAssociations();
foreach my $association (@associations) {
    if ( grep {$_ eq $association->Name()} @agentConfAssociationDeletionsList) {
        print "pushing " . $association->Name() . "\n";
        push(@associationsToRemove, $association);
    }
}

Итак, GetAssociations () вызывается перед первой итерацией петля. Здесь нет слова «не удалять во время итерации», что ловушка обычно возникает внутри each петель на основе и в стиле C for петли. Проблема, вероятно, что-то внутри RemoveAssocition() Метод.

Другая возможность состоит в том, что $association объекты возвращаются из GetAssociations() не копируются полностью, когда возвращаются обратно: Объекты $association могут быть внутренними данными из $agentConf. Это может быть скрытая ловушка «не удаляй при повторении», трудно сказать, не зная о реализации $agentConf или даже о том, каков ее интерфейс.

Кроме того, вы пропускаете символ на agentConf во втором цикле, но это, вероятно, просто опечатка.

2 голосов
/ 01 ноября 2010

Какие «странные результаты» вы получаете? Код, который вы опубликовали, не имеет явных проблем (вы не изменяете @associationsToRemove во время перебора, поэтому «не удалять из списка, над которым вы перебираете» не применяется), так что я склонен подозревать, что настоящая проблема в agentConf->RemoveAssociation.

1 голос
/ 01 ноября 2010

вы можете использовать такой подход хэша, как

my %h = map {$_ => 1 } @agentConfAssociationDeletionsList;
if (exists $h{$agentConfAssociationDeletionsList}) {
   delete  $h{$agentConfAssociationDeletionsList}; # like that
}
0 голосов
/ 01 ноября 2010

Сделайте копию исходного списка и выполните итерацию копии при удалении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...