简体   繁体   English

Lambda 或 LinQ 表达式从列表中删除某些对象

[英]Lambda or LinQ expression to remove certain objects from List

I have a cart.Lines List and want to remove all items where quantity == 0我有一个 cart.Lines 列表,想删除数量 == 0 的所有项目

This is a list that holds collection of CartLine objects:这是一个包含 CartLine 对象集合的列表:

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 !我只得到 Remove 和 RemoveAt,而不是 RemoveAll !

Also can't remove in a foreach loop, get error: Collection was modified;也无法在 foreach 循环中删除,出现错误:集合已修改; 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); cart.Lines = cart.Lines.Where(x => x.Quantity;= 0);

If Lines is a List<T> , then the simplest way is to just write:如果 Lines 是List<T> ,那么最简单的方法就是编写:

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.但是,如果 Lines 是一个IEnumerable<T> ,您可以 select 否定(正如 Vlad 建议的那样)-您也可以使用ToList()更改为列表,然后执行RemoveAll()但这将是矫枉过正。

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:既然您说 Lines 是IList<T> ,那么您将需要 select 否定并转换为如下列表:

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:或者您可以使用ToList()转换为List<T>然后调用RemoveAll()然后保存回来:

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.顺便说一句,作为一个仅供参考,我同时建立了一个删除列表,然后使用Remove()与使用Where()选择否定并调用ToList()和 Where/ToList 组合要快得多,这是有道理的,因为两者都分配 memory,但是Where/ToList 的 memory 洗牌要少得多。

Here's the timing for removing all the even numbers out of a list of 100,000 ints:这是从 100,000 个整数列表中删除所有偶数的时间:

  • Removing all evens building a remove list and calling Remove() on each took: 3921 ms删除所有构建删除列表并在每个事件上调用 Remove() 的事件:3921 毫秒
  • Removing all evens using Where() on negative and then ToList() took: 2 ms在负数上使用 Where() 然后 ToList() 删除所有偶数:2 ms
  • Removing all evens using ToList() on original then RemoveAll() took: 1 ms在原始上使用 ToList() 删除所有偶数,然后 RemoveAll() 花费:1 毫秒

Assuming that cart.Lines is List<>: cart.Lines.RemoveAll(x => x.Quantity == 0);假设 cart.Lines 是 List<>: cart.Lines.RemoveAll(x => x.Quantity == 0);

var myResult = cart.Lines.Where(x => x.Quantity > 0)

Alternatively you can use RemoveAll或者,您可以使用RemoveAll

cart.Lines.RemoveAll(x => x.Quantity == 0)

Check this post that answers your question C# using LINQ to remove objects within a List检查这篇回答您问题的帖子 C# 使用 LINQ 删除列表中的对象

These queries essentially foreach over a list, and as you know, you shouldn't use them to directly modify the list.这些查询本质上是对一个列表的 foreach,如您所知,您不应该使用它们直接修改列表。 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是的,我忘了你可以在一行中使用 RemoveAll 来做到这一点:D

I will go ahead and post my suggestion to this problem.我会提前 go 并发布我对这个问题的建议。

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;   

You can do it as follows:你可以这样做:

Cart cart = new Cart();
List<CartLine> cartLines = cart.Lines.ToList<CartLine>();
cartLines.RemoveAll(x => x.Quantity == 0);
cart.Lines = cartLines;

Also, you should set the CartLine Quantity and Product properties as public.此外,您应该将 CartLine Quantity 和 Product 属性设置为 public。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM