views:

137

answers:

4

In C++ using std::list, this is a simple matter of erasing what an iterator is pointing to (the erase statement returns the next valid member of the list).

What's the best way to iterator through a list and remove members that match a certain criteria?

+1  A: 

if you talking about foreach and using IEnumerator the answer is that you cannot remove anything from IEnumerable while iterating through it. The only way is to store something (indexes of items) in another list and next delete them in loop

But here is the cookie: http://www.koders.com/csharp/fidF2C8E1786AE76101911914CCA9286E25B398AED6.aspx?s=textbox

" Allows you to modify the underlying collection while in the middle of a foreach"

Trickster
+3  A: 

Assuming you have a List<T>, one efficient way is to iterate through the list in reverse order, removing items as you go:

for(int i = myList.Count-1; i--; i>=0)
{
    if (ShouldBeRemoved(myList[i]))
    {
        myList.RemoveAt(i);
    }
}

If you instead have IEnumerable<T>, it gets more difficult as you can't alter a list while iterating.

Bevan
+2  A: 

In .NET you can't modify underlying collection during iteration with enumerator. So you have to options:

  • iterate over your list with good ol' for(;;) loop;

  • create a new list without items matching your criteria:

    var list1 = ...; var list2 = list1.Where(item => !criteria(item)).ToList();

(I've used C# for this sample but you should be able to convert it to VB).

elder_george
+8  A: 

List<T> has the RemoveAll method, that takes a predicate and removes items: http://msdn.microsoft.com/en-us/library/wdka673a.aspx

dinosaurs.RemoveAll(AddressOf EndsWithSaurus)

Private Shared Function EndsWithSaurus(ByVal s As String) _
    As Boolean
    If (s.Length > 5) AndAlso _
        (s.Substring(s.Length - 6).ToLower() = "saurus") Then
        Return True
    Else
        Return False
    End If
End Function
Kobi
+1 for predicates. I believe this is thread safe as well.
Soviut
@Soviut: `List<T>` is not a thread-safe class, nor is the `RemoveAll` method (it never takes a lock).
bobbymcr
I like this a lot -- however, I'd like to have a list of all the junk that was RemoveAll'd so that I can process the rejects.
hamlin11