Reputation: 15463
I was writing some ASP.NET control when I came to the scenario where I needed to remove items from a list, only when they matched a certain condition.
The RemoveAll
method of the generic List
class does a good job, but removes all items that match the condition, specified by the predicate.
What if I want to only remove a certain number of items specifying the condition? What do you think is the best way to do this?
Upvotes: 2
Views: 821
Reputation: 23766
If you want to specify both a limit for number of items to remove and a condition to select the items to remove, you can use this approach:
int limit = 30; // Suppose you want to remove 30 items at most
list.RemoveAll(item => ShouldIRemoveThis(item) && limit-- > 0);
Upvotes: 8
Reputation: 29573
@buyutec
Instead of
list.RemoveAll(item => ShouldIRemoveThis(item));
you can use:
list.RemoveAll(ShouldIRemoveThis);
The lambda has the same signature as the method, so they are equivalent so you can just pass the method directly.
Upvotes: 5
Reputation: 49376
Anonymous delegates are useful here. A simple example to remove the first limit even numbers from a list.
List<int> myList = new List<int>;
for (int i = 0; i < 20; i++) myList.add(i);
int total = 0;
int limit = 5;
myList.RemoveAll(delegate(int i) { if (i % 2 == 0 && total < limit) { total++; return true; } return false; });
myList.ForEach(i => Console.Write(i + " "));
Gives 1 3 5 7 9 10 11 12 13 14 15 16 17 18 19, as we want. Easy enough to wrap that up in a function, suitable for use as a lambda expression, taking the real test as a parameter.
Upvotes: 0
Reputation: 22577
Unless the method provides a "limit" parameter (which it doesn't) your best option is to go with a simple loop that removes the items that match, breaking when your incremented "match counter" hits your limit.
That's pretty much how the internal function works anyway, but in a more optimized way.
Upvotes: 1
Reputation: 53115
Can you use LINQ? If so, you can just use the .Take() method and specify how many records you want (maybe as total - N).
Upvotes: 0
Reputation: 23766
In framework 3.5, RemoveAll method takes a predicate as a parameter. So you may use
list.RemoveAll(item => ShouldIRemoveThis(item));
where ShouldIRemoveThis is a method that returns a boolean indicating whether the item must be removed from the list.
Upvotes: 1