LINQ用于基于IList<int>从IList<T>中移除特定元素

10

如何使用LINQ基于另一个IList从IList中删除特定元素。我需要从list1中删除ID存在于list2中的记录。以下是代码示例,

class DTO
{

    Prop int ID,
    Prop string Name
}

IList<DTO> list1;

IList<int> list2;



foreach(var i in list2)
{
    var matchingRecord = list1.Where(x.ID == i).First();
    list1.Remove(matchingRecord);
}

这是我正在做的方式,有更好的方法来做同样的事情吗。


6
每天都有类似的问题。 - Tim Schmelter
不要使用Linq。Linq主要用于过滤和创建新序列,而不是修改集合。 - Matthew Watson
3个回答

25
您可以编写一个针对 IList<T> 的“RemoveAll()”扩展方法,其功能与 List.RemoveAll() 完全相同。(这通常足够常用,可以保留在共享类库中。)
例如(为了清楚起见,已删除错误检查;您需要检查参数不为空):
public static class IListExt
{
    public static int RemoveAll<T>(this IList<T> list, Predicate<T> match)
    {
        int count = 0;

        for (int i = list.Count - 1; i >= 0; i--)
        {
            if (match(list[i]))
            {
                ++count;
                list.RemoveAt(i);
            }
        }

        return count;
    }        

然后,要根据需要从list1中删除项目的操作实际上变得非常简单:

list1.RemoveAll(item => list2.Contains(item.ID));

16

我会采用这种方法:

var itemsToRemove = list1.Where(x => list2.Contains(x.ID)).ToList();
foreach(var itemToRemove in itemsToRemove)
    list1.Remove(itemToRemove);

这种方法会在原地删除项目。它最适用于list1中有许多项目而list2中只有少数项目的情况。
如果list1list2中的项目数量相似,则Cuong Le的方法是一个很好的选择。


1
为什么在 Where 后面加上 ToList()?我认为这不是必要的。 - George Duckett
3
@GeorgeDuckett:是的,这是必要的。否则,itemsToRemove会在list1上进行迭代。与Remove一起使用会导致InvalidOperationException已修改集合;可能无法执行枚举操作 - Daniel Hilgarth
啊,好的,谢谢提醒,我忘了那个。 - George Duckett
我给你的解决方案投了反对票,因为与被接受的答案相比,我觉得你的解决方案真的很糟糕。你复制了要删除的元素,这是完全没有必要的。这样做会占用更多的空间和时间。 - undefined

8
您可以使用Where来简化操作:
list1 = list1.Where(x => !list2.Contains(x.ID))
             .ToList();

但是你真的需要进行原地删除,建议使用@DanielHilgarth的答案。

3
RemoveAll方法不会返回一个列表,而是会返回一个整数,该整数表示已删除的项的数量。 - Robert J.
@RobertJ. 你应该使用RemoveAll,看看我的回答。 - Michiel van Vaardegem
这实际上在他的回答中已经提到了,因此我才发表了我的评论。 - Robert J.
没关系,它是一个IList。 - Michiel van Vaardegem
@Cuong le:这就是我一直在寻找的。我认为这会起作用。谢谢。 - passionatedeveloper
为什么你推荐使用 @DanielHilgarth 的方法,而不是使用原地删除。它使用了 "ToList"。你应该推荐:Matthew Watson 的答案(被接受的答案)。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接