Lambda or LinQ expression to remove certain objects from List
Solution 1
If Lines is a List<T>
, then the simplest way is to just write:
cart.Lines.RemoveAll(x => x.Quantity == 0);
If Lines is an IEnumerable<T>
, though, you could select the negative (as Vlad suggested) - you could also change to a list using ToList()
and then do RemoveAll()
but that would be overkill.
cart.Lines = cart.Lines.Where(x => x.Quantity != 0);
UPDATE:
Since you said Lines is an IList<T>
, then you will want to select the negative and convert to a list like:
cart.Lines = cart.Lines.Where(x => x.Quantity != 0).ToList();
Or you can conver to a List<T>
using ToList()
then call RemoveAll()
and then save back:
var temp = cart.Lines.ToList();
temp.RemoveAll(x => x.Quantity != 0);
cart.Lines = temp;
Incidentally, as an FYI I timed both building a remove list and then using Remove()
vs selecting the negative using Where()
and calling ToList()
and the Where/ToList combo was much faster which makes sense because both allocate memory, but the Where/ToList does a lot less memory shuffling.
Here's the timing for removing all the even numbers out of a list of 100,000 ints:
- Removing all evens building a remove list and calling Remove() on each took: 3921 ms
- Removing all evens using Where() on negative and then ToList() took: 2 ms
- Removing all evens using ToList() on original then RemoveAll() took: 1 ms
Solution 2
Assuming that cart.Lines is List<>: cart.Lines.RemoveAll(x => x.Quantity == 0);
Solution 3
These queries essentially foreach over a list, and as you know, you shouldn't use them to directly modify the list. Rather you should make a list of the items to be removed using the query, and then remove them in a separate operation.
EDIT:
yeh, I forgot you can use RemoveAll to do this in one line :D
Solution 4
var myResult = cart.Lines.Where(x => x.Quantity > 0)
Alternatively you can use RemoveAll
cart.Lines.RemoveAll(x => x.Quantity == 0)
Check this post that answers your question C# using LINQ to remove objects within a List
Solution 5
I will go ahead and post my suggestion to this problem.
private IList<CartLine> lines = new List<CartLine>();
should be:
private List<CartLine> lines = new List<CartLine>();
This will allow you to use the suggested method of:
cart.Lines.RemoveAll(x => x.Quantity == 0);
You do exactly that by doing it this way:
var myList = cart.Lines.ToList();
myList.RemoveAll(x => x.Quantity == 0);
cart.Lines = myList;
LaserBeak
Updated on June 04, 2022Comments
-
LaserBeak almost 2 years
I have a cart.Lines List and want to remove all items where quantity == 0
This is a list that holds collection of CartLine objects:
public class Cart { private IList<CartLine> lines = new List<CartLine>(); public IList<CartLine> Lines { get { return lines; } set { lines = value; } } } public class CartLine { Product Product {get; set;} int Quantity {get; set;} }
So something like:
cart.Lines.RemoveAll(x => x.Quantity == 0)
I only get Remove and RemoveAt, not RemoveAll !
Also can't remove in a foreach loop, get error: Collection was modified; enumeration operation may not execute.
I have now managed to do it with this code, surely there must be something more efficient ?
var myList = cart.Lines.ToList(); myList.RemoveAll(x => x.Quantity == 0); cart.Lines = myList;
Okay Problem solved!Thanks guys, this here does it:
cart.Lines = cart.Lines.Where(x => x.Quantity != 0);
-
treetey almost 13 yearsSo use
cart.Lines = cart.Lines.Where(x => x.Quantity > 0).ToList()
-
Security Hound almost 13 years@LaserBeak - Why exactly are you using interface collection instead of the generic List collection?
-
James Michael Hare almost 13 years@Ramhound, he's probably trying to decouple the implementation a bit from the interface. A lot of code analysis tools tend to recommend using IList<T> or ICollection<T> instead of List<T> directly. Not saying that's necessarily good or bad, just something that comes up a lot. Yeah, he added the IList<T> clarification in an edit.