Lambda or LinQ expression to remove certain objects from List

11,547

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;   
Share:
11,547
LaserBeak
Author by

LaserBeak

Updated on June 04, 2022

Comments

  • LaserBeak
    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
    treetey almost 13 years
    So use cart.Lines = cart.Lines.Where(x => x.Quantity > 0).ToList()
  • Security Hound
    Security Hound almost 13 years
    @LaserBeak - Why exactly are you using interface collection instead of the generic List collection?
  • James Michael Hare
    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.