开发者

Safe way to remove elements from a list in Perl?

I'm having some weird results from this perl code - I need to delete several elements from a list of Association objects.

My approach is to scan the list once, push the matches to another array, then iterate that array and delete each one, but I haven't escaped the "don't delete while iterating pitfall".

Any ideas on how to avoid this? Many thanks.

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

#find associations to remove
my @associationsToRemove = ()开发者_StackOverflow;
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);
}


Your first loop is this:

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

which is equivalent to this:

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

So, GetAssociations() is called before the first iteration of the loop. There is no "don't delete while iterating pitfall" here, that pitfall generally comes up insideeach based loops and C-style for loops. The problem is probably something inside the RemoveAssocition() method.

Another possibility is that the $association objects returned from GetAssociations() aren't fully copied when they're passed back: the $association objects could still be internal data from $agentConf. This could be a hidden "don't delete while iterating" pitfall, hard to say without knowing the implementation of $agentConf or even what its interface is.

Also, you're missing a sigil on agentConf in your second loop but that's probably just a typo.


What sort of "weird results" are you getting? The code you posted has no obvious problems in it (you aren't changing @associationsToRemove while iterating over it, so "don't delete from a list you're iterating over" doesn't apply), so I'm inclined to suspect that the actual problem is in agentConf->RemoveAssociation.


you can use hash approach like this,

my %h = map {$_ => 1 } @agentConfAssociationDeletionsList;
if (exists $h{$agentConfAssociationDeletionsList}) {
   delete  $h{$agentConfAssociationDeletionsList}; # like that
}


Make a copy of the original list, and iterate through the copy when deleting.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜