2009-07-26 65 views
27

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

通常情况下,我会做消除这样的:

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

更具体地讲,其实我建立或填充动态类(不是一个正式的定义的类)的toBeRemvoedItems名单。例如,T舱是像MyClass的和代码去除是:

class MyClass<C> { 
    public string Value1 { get; set; } 
    public int Value2 { get; set; } 
    public C ObjectC { get; set; } 
} 
.... 
List<MyClass<C>> 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()有方法(它是有道理的IEnumerable仅用于枚举)。在List类中,有几个超载的方法。我不确定是否有其他方法通过使用LINQ或Lambda表达式从列表中删除项目?

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

+0

看起来像一个笨蛋。那么,基本上你提到了所有可能的方法在帖子本身... http://stackoverflow.com/questions/1120336/what-is-the-easiest-way-to-foreach-through-a-listt-removing-unwanted -objects – 2009-07-26 19:36:18

回答

40

你可以使用方法removeall过

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

我认为它实际上是表的方法,而不是扩展方法 – Jimmy 2009-07-26 19:29:30

+0

谢谢!我更新了我的帖子。 – 2009-07-26 19:30:43

+0

我了解你的代码是你一次删除一个项目。我仍然必须像Rchard Hein的建议一样循环。 – 2009-07-26 20:07:09

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

太又迟到了。好吧。

+0

不知道是否可以将两个参数传递给RemoveAll(lambda func)以除去toBeRemovedItems,而不通过foreach循环。肯定它已经很可读了。 – 2009-07-26 20:09:35

21

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

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

这不会更新原有List<T>实例,而是将创建一个新IEnumerable<T>与删除的值。

+0

什么是性能。打这样做与一个for循环删除项目? – 2015-08-23 21:29:38

4

我同意过滤掉某些项目的Jared的建议,但它看起来像Value1一个join将是一个更有效的方法:

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更有效率。

5

如果我正确地得到问题,从两个列表中产生一个唯一的集合。

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

List list1; List list2;

List list3 = list1。除(列表2)

的项目list3将包含独特的项目。

1

对于不属于列表(不能暴露RemoveAll),你仍然可以删除与一个班轮项目的集合。

要更换直列,只是生成项目的列表中删除,然后通过运行它,并执行删除代码。

var dictionary = new Dictionary<string, string>(){{"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<string, string>(){{"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); 
0

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

List<T> firstList; 
List<T2> toBeRemovedItems; 
List<T> finalList; 

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

这是我如何设法解决的问题有List<ViewModel>List<Model>之间摆脱重复的。我使用CheckIfWeRemoveThisOne函数检查item.Number是否属于某个其他项目,并使用ID作为定义特性。如果发现了另一个项目(一式两份),而不是试图从原来的列表中删除(这让我取回一个List<Model>和被赋予了List<ViewModel>到我摆在首位的功能,所以我有我的怀疑,我怎么无论如何,我可以做到),我只是建立了一个新的列表 - 如果发现它是好的,那就把结果添加进去。

相关问题