使用LINQ或Lambda从列表中删除实例?

现在我来了一个阶段,将我的所有数据作为缓存(对象)中的列表,我接下来要做的是从列表中删除一些实例。

通常情况下,我会这样删除:

List list; List toBeRemovedItems; // populate two lists foreach(T2 item in toBeRemovedItems) { list.Remove(delegate(T one) { // build a condition based on item // return true or false }); } 

更具体地说,我实际上构建或填充了动态类(不是正式定义的类)的BeRemvoedItems列表。 例如,T类类似于MyClass,删除代码是:

 class MyClass { public string Value1 { get; set; } public int Value2 { get; set; } public C ObjectC { get; set; } } .... List<MyClass> list; // populate list // populate toBeRemovedItems. Here is an example of hard-coded codes: var toBeRemovedLItems = new[] { new { Value1="a", Value2 = 1}, new { Value2="x", Value2 = 10}, ... }; // toBeRemovedItems may be the result of Select from a collection foreach(var item in toBeRemovedLItems) { list.Remove(delegate(MyClass one) { return one.Value1 = item.Value1 && one.Value2 < item.Value2; }); } 

我试图从MSDN中搜索IEnumerable接口中的Remove()方法,但我找不到Remove()的方法Remove() IEnumerable仅用于枚举)。 在List类中,有几个重载的Remove(...)方法。 我不确定是否有其他方法可以使用LINQ或Lambda表达式从列表中删除项目?

顺便说一下,我想到了一种方法来对列表进行查询,以获得具有Where条件的子集或新的IEnumerable列表,类似于从列表中移动项目。 但是,我更喜欢从缓存列表中删除项目,在某些情况下,我只是无法将类中的列表属性重置为新列表(例如私有集)。

您可以使用RemoveAll方法:

 MyClass one; //initialize MyClass list.RemoveAll(item => one.Value1 == item.Value1 && one.Value2 < item.Value2); 

您可以使用LINQ的Where方法过滤掉不应该是列表一部分的值。 结果是一个IEnumerable ,删除了元素。

 var res = list.Where(item => !(one.Value1 == item.Value1 && one.Value2 < item.Value2)); 

这不会更新原始的List实例,而是会创建一个删除了值的新IEnumerable

如果我正确地得到了问题,从两个List中生成一个唯一的集合。

为此,您可以使用以下内容

清单list1; 清单list2;

列表list3 = list1.Except(list2)

list3将包含唯一的项目。

我同意Jared关于过滤某些项目的建议,但看起来像Value1join将是一种更有效的方法:

 var res = from item1 in list join item2 in toBeRemovedList on item1.Value1 equals item2.Value1 where item1.Value2 >= item2.Value2 select item1; 

更新:显然我在阅读理解上失败了 – 新方法:

 var removeDict = toBeRemovedList.ToDictionary(i => i.Value1, i => i.Value2); list.RemoveAll(item => { int itemToRemoveValue2; if(removeDict.TryGetValue(item.Value1, out itemToRemoveValue2)) return item.Value2 < itemToRemoveValue2; return false; }); 

当然,如果要删除的列表可以以字典开头,那就更好了。 最终,我们只是想让我们在Value1上的匹配更有效率。

 foreach(var item in toBeRemovedLItems) { list.RemoveAll(one => one.Value1 == item.Value1 && one.Value2 < item.Value2); } 

太晚了。 那好吧。

对于非列表的集合(无法公开RemoveAll ),您仍然可以使用单行删除项目。

要替换内联,只需生成要删除的项列表,然后运行它并执行删除代码。

 var dictionary = new Dictionary(){{"foo", "0"}, {"boo", "1"}, {"goo", "1"}}; dictionary .Where(where_item => ((where_item.Key == "foo") && (where_item.Value == "0")) || ((where_item.Key == "boo") && (where_item.Value == "1")) ) .ToList() .ForEach(remove_item => { dictionary.Remove(remove_item.Key); }); 

要替换副本,只需生成已过滤的可枚举项并返回新副本。

 var dictionary0 = new Dictionary(){{"foo", "0"}, {"boo", "1"}, {"goo", "1"}}; var dictionary1 = dictionary0 .Where(where_item => ((where_item.Key == "foo") && (where_item.Value == "0")) || ((where_item.Key == "boo") && (where_item.Value == "1")) ) .ToDictionary(each_item => each_item.Key, each_item => each_item.Value); 

也许你正试图做这样的事情?

 List firstList; List toBeRemovedItems; List finalList; foreach(T item in firstList) { toBeRemovedItems = CheckIfWeRemoveThisOne(item.Number, item.Id); if (toBeRemovedItems == null && toBeRemovedItems.Count() == 0) finalList.Add(item); } 

这就是我设法解决ListList之间的重复问题。 我使用CheckIfWeRemoveThisOne函数来检查item.Number属于某个其他项目,使用ID作为定义特征。 如果它找到另一个项目(一个副本),而不是尝试从原始列表中删除它(我回到了List并且首先将List放入我的函数中,所以我有我怀疑我怎么能这样做,无论如何),我刚刚建立了一个新的清单 – 如果发现它是好的,将结果添加到其中。