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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1185323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 10:18:29  来源:igfitidea点击:

Remove instances from a list by using LINQ or Lambda?

c#linqlambda

提问by David.Chu.ca

Now I come a stage to get all my data as a list in cache(objects) and my next thing I have to do is to remove some instances from the list.

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

Normally, I would do removing like this:

通常,我会像这样删除:

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
    });
}

To be more specific, I actually build or populate toBeRemvoedItems list of a dynamic class (not a formal defined class). For example, the T class is something like MyClass and codes for removing are:

更具体地说,我实际上构建或填充动态类(不是正式定义的类)的 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;
    });
}

I tried to search for Remove()method in IEnumerableinterface from MSDN, but I cannot find the method of Remove()there (it makes sense that IEnumerableis used just for enumeration). In List class, there are several overloaded Remove(...)methods. I am not sure if there any alternative ways to remove items from a list by using LINQ or Lambda expressions?

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

By the way, I thought about a way to do a query against a list to get a subset or a new IEnumerablelist with Where conditions, similar as moving items from a list. However, I prefer to remove items from my cached list, and there some cases I just cannot reset list property in a class to a new list (private set for example).

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

回答by Francis B.

You could use the method RemoveAll:

您可以使用RemoveAll方法:

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

回答by Richard Anthony Hein

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

Too late again. Oh well.

又来晚了。那好吧。

回答by JaredPar

You can use LINQ's Where method to filter out values that should not be a part of the list. The result is an IEnumerable<T>with the elements removed.

您可以使用 LINQ 的 Where 方法过滤掉不应属于​​列表的值。结果是IEnumerable<T>删除了元素。

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

This will not updated the original List<T>instance but instead will create a new IEnumerable<T>with the values removed.

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

回答by dahlbyk

I agree with Jared's suggestion of filtering out certain items, but it looks like a joinon Value1would be a more efficient approach:

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

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

Update:Apparently I fail at reading comprehension - new approach:

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

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;
});

Of course, it would be even better if your list to remove could start as a dictionary. Ultimately, we're just trying to make our match on Value1more efficient.

当然,如果您要删除的列表可以从字典开始,那就更好了。最终,我们只是想让我们的比赛Value1更有效率。

回答by dahlbyk

If I get the question correctly, to produce a unique set from two List.

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

For this, you can use the following

为此,您可以使用以下

List list1; List list2;

清单 list1; 清单 list2;

List list3 = list1.Except(list2)

列表 list3 = list1.Except(list2)

The list3 will contain unique items.

list3 将包含独特的项目。

回答by Alex

For collections that are not lists (can't expose RemoveAll), you can still remove items with a one-liner.

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

To replace inline, just generate a list of items to remove, then run through it and execute remove code.

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

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);
    });

To replace in copy, just generate a filtered enumerable and return a new copy.

要在副本中替换,只需生成一个过滤的可枚举并返回一个新副本。

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);

回答by vapcguy

Maybe you're trying to do something like this?

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

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);
}

This is how I managed to solve an issue with getting rid of duplicates between a List<ViewModel>and a List<Model>. I used the CheckIfWeRemoveThisOnefunction to check if the item.Numberbelonged to some other item, using the ID as the defining characteristic. If it found another item (a duplicate), rather than try and remove it from the original list (which I was getting back a List<Model>and was given a List<ViewModel>into my function in the first place, so I had my doubts as to how I could do it, anyway), I just built a new list -- adding the result into it if it was found to be ok.

这就是我设法解决消除 aList<ViewModel>和 a之间重复项的问题的方法List<Model>。我使用该CheckIfWeRemoveThisOne函数来检查是否item.Number属于某个其他项目,使用 ID 作为定义特征。如果它找到另一个项目(重复),而不是尝试将其从原始列表中删除(我正在取回 aList<Model>并首先将 a 分配List<ViewModel>到我的函数中,所以我怀疑我该怎么做无论如何),我只是建立了一个新列表——如果发现结果没问题,就将结果添加到其中。