从一个IList<>中移除另一个IList<>中的项目

9

非常抱歉提出这样基础的问题,我对LINQ不熟悉,正在尝试找到在不通过循环遍历每个 IList 的情况下完成操作的最佳方法。

我有两个包含自定义DTO对象的 ILists<>,我想从其中一个列表中删除所有与另一个列表中匹配的项目。

IList<ItemDTO> list1 = itemsbl.GetBestItems();
IList<ItemDTO> list2 = itemsbl.GetWorstItems();

我需要从list2中删除所有list1中的项目。我一直在查看Except()方法,但显然我需要让我的ItemsDTO类覆盖GetHashCodeEquals方法才能使其工作,但我很难找到一些这方面的例子。
请问有人能向我展示从list2中删除list1的最佳方法吗?
谢谢。
4个回答

9
您可以使用 Except 方法来实现此功能。
var newList = list2.Except(list1).ToList();

如果您想替换list2,则只需执行以下操作:
list2 = list2.Except(list1).ToList();

来自 MSDN:

要比较自定义数据类型,实现 IEquatable 泛型接口,并为该类型提供您自己的 GetHashCode 和 Equals 方法。默认的相等比较器 Default 用于比较实现了 IEquatable 接口的类型的值。


谢谢,最终我修改了我的类,以便我可以使用 Except()... 谢谢大家,我相信所有其他的解决方案也同样好... :) - Nugs

1

哈希绝对是一种好方法,@Jon Skeet在下面提供了类似问题的答案,这将为您提供解决方案。

所以基本语法是:

 var setToRemove = new HashSet<ItemDTO>(list1);
 list2.RemoveAll(x => setToRemove.Contains(x));

使用 LINQ 从 List<T> 中移除元素

希望这有所帮助。


我不知道为什么,但RemoveAll()对我来说不是一个选项... - Nugs
3
IList是由List实现的接口,它可以用于其他集合类。List类包含的方法可能不会在IList中定义。因此,将原始列表对象分配给IList后,您将无法再访问List的任何独有方法。除非您有使用IList<ItemDTO>的原因,否则建议使用List<ItemDTO>。MSDN文档链接:http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx - Nickz

1
var list1 = new List<string> { "A", "B", "C" };
var list2 = new List<string> { "A", "C", "E", "B", "D", "G", "F" };
list2.RemoveAll(list1.Contains);

这也可以工作。请注意,list1.Contains实际上是一个lambda表达式

s => list1.Contains(s)

-A.


我不知道为什么,但RemoveAll()对我来说不是一个选项... - Nugs
list.Contains 实际上不是一个 lambda 表达式,尽管在这里它的行为相同。 - svick
1
我提到这个是因为我认为RemoveAll采用谓词很重要,特别是因为OP的对象可能没有实现相等/比较。 - Ani
RemoveAll 只存在于 List<T> 上。如果你正在使用 IList<T>,那么你将无法使用它。 - Carl Bussema
正如已经说明的那样,IList<T> 接口不包含 RemoveAll 方法。 - Luke
@Coulton,这些澄清是编辑而来的。最初的问题并不清楚,我把答案留在这里供其他人查找。无论如何,感谢您的投票。 - Ani

0
这段内容与编程有关。它的意思是你需要告诉 .net 运行时如何确定两个类的实例是否相等(例如,它应该如何定义一个 ItemDTO 实例是否等于另一个 ItemDTO 实例)。
为了做到这一点,需要重写 Equals 方法。
public class ItemDTO
{
    public override bool Equals(object obj)
    {
        var otherItem = obj as ItemDTO;

        if (otherItem == null)
        {
            // this will be because either 'obj' is null or it is not of type ItemDTO.
            return false;
        }

        return otherItem.SomeProperty == this.SomeProperty 
               && otherItem.OtherProperty == this.OtherProperty;
    }
}

如果您不这样做,它只会删除列表中指向与其他物理实例相同的引用。然后,您可以使用Except或RemoveAll方法或任何其他您决定使用的方法。

您还需要重写GetHashcode,请参阅下面的链接以获取更多信息。

请参见重载Equals和GetHashcode的准则


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