tags:

views:

323

answers:

7

In c#, when I want to remove some items from a list, i do it in the following way,

List<Item> itemsToBeRemoved = new List<Item>();
foreach(Item item in myList)
{
   if (IsMatching(item)) itemsToBeRemoved.Add(item);
}

foreach(Item item in itemsToBeRemoved)
{
   myList.Remove(item);
}

Is there any better way to do it?

+1  A: 

How about reverting your logic, adding items which doesn't match and just use the result collection?

List<Item> itemsTaken = new List<Item>();
foreach(Item item in myList)
{
   if (!IsMatching(item)) itemsTaken.Add(item);
}

// use itemsTaken as if it were myList with items removed
Adrian Godong
that depends on the ratio of number of items to be removed and items to be retained in the list.
gilbertc
+2  A: 

Here's a bit of an improvement using Linq.

var itemsToRemove = myList.Where(item => IsMatching(item)).ToList();
foreach(Item item in itemsToBeRemoved)
{
   myList.Remove(item);
}
Jake Pearson
+12  A: 
myList.RemoveAll(x=> IsMatching(x));
Brandon
And if you want, you don't even have to use the lambda. The compiler will automatically convert "IsMatching" to Predicate<T>.
Eric Lippert
+1 But this not LINQ, this is just method on List<T>.
Mike Chaliy
Also, why do you say "if you can use LINQ"? What does this have to do with LINQ?
Eric Lippert
Sorry, I was halfway typing up another version of my answer, when I replaced it with this. Forgot to remove the intro.
Brandon
Following his example, I think you want myList, rather than itemsToBeRemoved. Still, good answer, +1
Matt Grande
@Matt, you are correct. I really need more coffee.
Brandon
RemoveAll() is a method if List<T>, so it has nothing to do with LINQ.
Philippe Leybaert
+1  A: 

What I used to do is the create a reverse for-loop:

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

But I'm sure there are more elegant ways using LINQ.

M4N
Why a downvote? This works!
M4N
I got downvoted too! What the frig!
Matt Grande
+17  A: 

Well, you could call the method that does exactly what you want.

myList.RemoveAll(IsMatching)

Generally it is "better" to use the method that does exactly what you want rather than re-inventing it yourself.

Eric Lippert
obviously I have overlooked this method.. thanks!!
gilbertc
A: 

Similar to what Jakers said, and assuming you are on .Net 3:

myList = myList.Where(item => !IsMatching(item)).ToList();
Matt Grande
A: 
foreach(Item singleItem in new List<Item>(allItems))
{
  if(IsMatching(singleItem))
     allItems.Remove(singleItem);
}
ben
I could be wrong, but I didn't think you could modify an array while iterating over it using foreach.
Matt Grande
He's not modifying it. He's made a copy, is iterating over the copy, and is modifying the original.
Eric Lippert
Ahh, so he is. Didn't notice that the first time.
Matt Grande