Which is the easiest way to remove items that match some condition from a list and then, get those items.
I can think in a few ways, I don't know which is the best one:
var subList = list.Where(x => x.Condition);
list.RemoveAll(x => x.Condition);
or
var subList = list.Where(x => x.Condition);
list.RemoveAll(x => subList.Contains(x));
Is any of this one of the best ways? If it is, which one? If it's not, how should I do it?
I would go with the first option for readability purposes, with the note that you should materialize the list first, or you'll lose the very items you're trying to select on the next line:
var sublist = list.Where(x => x.Condition).ToArray();
list.RemoveAll(x => x.Condition);
The second example is O(n^2) for no reason and the last is perfectly fine, but less readable.
Edit: now that I reread your last example, note that as it's written right now will take out every other item. You're missing the condition check and the remove line should actually be list.RemoveAt(i--);
because the i+1
th element becomes the i
th element after the removal, and when you increment i
you're skipping over it.
I like to use a functional programming approach (only make new things, don't modify existing things). One advantage of ToLookup
is that you can handle more than a two-way split of the items.
ILookup<bool, Customer> lookup = list.ToLookup(x => x.Condition);
List<Customer> sublist = lookup[true].ToList();
list = lookup[false].ToList();
Or if you need to modify the original instance...
list.Clear();
list.AddRange(lookup[false]);
The first option is good, but it makes two runs over collection. You can do it in one run by executing the additional logic inside predicate:
var removedItems = new List<Example>();
list.RemoveAll(x =>
{
if (x.Condition)
{
removedItems.Add(x);
return true;
}
return false;
});
You can also wrap it into extension for convinience:
public static class ListExtensions
{
public static int RemoveAll<T>(this List<T> list, Predicate<T> predicate, Action<T> action)
{
return list.RemoveAll(item =>
{
if (predicate(item))
{
action(item);
return true;
}
return false;
});
}
}
And use like this:
var removedItems = new List<Example>();
list.RemoveAll(x => x.Condition, x => removedItems.Add(x));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With