Slavo
Slavo

Reputation: 15463

Removing N items from a list conditionally

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

Answers (6)

Serhat Ozgel
Serhat Ozgel

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

Wilka
Wilka

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

Adam Wright
Adam Wright

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

mercutio
mercutio

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

Jon Galloway
Jon Galloway

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

Serhat Ozgel
Serhat Ozgel

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

Related Questions