使用Linq除了不按我的想法工作

时间:2013-05-29 22:10:08

标签: c# .net linq list except

List1包含商品{ A, B }List2包含商品{ A, B, C }

当我使用Except Linq扩展时,我需要返回{ C }。相反,我得到了返回{ A, B },如果我在表达式中翻转列表,结果为{ A, B, C }

我是否误解了Except的观点?还有其他我没有看到使用的扩展吗?

到目前为止,我已经查看并尝试了很多关于这个问题的不同帖子,但没有成功。

var except = List1.Except(List2); //This is the line I have thus far
编辑:是的我正在比较简单的对象。我从未使用IEqualityComparer,了解它很有趣。

谢谢大家的帮助。问题不是实现比较器。链接的博客文章和示例如下有帮助。

5 个答案:

答案 0 :(得分:16)

如果要在列表中存储引用类型,则必须确保有一种方法可以比较对象是否相等。否则,将通过比较它们是否引用相同的地址来检查它们。

您可以实施IEqualityComparer<T>并将其作为参数发送到Except()功能。这是blog post您可能会觉得有帮助。

答案 1 :(得分:7)

你只是混淆了论证的顺序。我可以看到这种混乱出现的地方,因为official documentation并没有那么有用:

  

使用默认的相等比较器来比较值,生成两个序列的集合差异。

除非你精通集合论,否则可能不清楚set difference究竟是什么 - 它不仅仅是集合之间的不同之处。实际上,Except返回第一组中不在第二组中的元素列表。

试试这个:

var except = List2.Except(List1); // { C }

答案 2 :(得分:6)

所以只是为了完整......

// Except gives you the items in the first set but not the second
    var InList1ButNotList2 = List1.Except(List2);
    var InList2ButNotList1 = List2.Except(List1);
// Intersect gives you the items that are common to both lists    
    var InBothLists = List1.Intersect(List2);

编辑:由于您的列表包含对象,您需要为您的类传入IEqualityComparer ...以下是基于组合对象的示例IEqualityComparer的外观...:)

// Except gives you the items in the first set but not the second
        var equalityComparer = new MyClassEqualityComparer();
        var InList1ButNotList2 = List1.Except(List2, equalityComparer);
        var InList2ButNotList1 = List2.Except(List1, equalityComparer);
// Intersect gives you the items that are common to both lists    
        var InBothLists = List1.Intersect(List2);

public class MyClass
{
    public int i;
    public int j;
}

class MyClassEqualityComparer : IEqualityComparer<MyClass>
{
    public bool Equals(MyClass x, MyClass y)
    {
        return x.i == y.i &&
               x.j == y.j;
    }

    public int GetHashCode(MyClass obj)
    {
        unchecked
        {
            if (obj == null)
                return 0;
            int hashCode = obj.i.GetHashCode();
            hashCode = (hashCode * 397) ^ obj.i.GetHashCode();
            return hashCode;
        }
    }
}

答案 3 :(得分:0)

编写自定义比较器似乎可以解决该问题,但是我认为https://stackoverflow.com/a/12988312/10042740是一个更简单,更优雅的解决方案。

它会覆盖您的对象定义类中的GetHashCode()和Equals()方法,然后默认的比较器就可以发挥作用,而不会产生多余的代码。

答案 4 :(得分:-1)

仅供参考: 我想比较已连接且可用于系统的USB驱动器。

这是实现IEqualityComparer接口的类

public class DriveInfoEqualityComparer : IEqualityComparer<DriveInfo>
{
    public bool Equals(DriveInfo x, DriveInfo y)
    {
        if (object.ReferenceEquals(x, y))
            return true;
        if (x == null || y == null)
            return false;
        // compare with Drive Level
        return x.VolumeLabel.Equals(y.VolumeLabel);
    }

    public int GetHashCode(DriveInfo obj)
    {
        return obj.VolumeLabel.GetHashCode();
    }
}

您可以像这样使用它

var newDeviceLst = DriveInfo.GetDrives()
                            .ToList()
                            .Except(inMemoryDrives, new DriveInfoEqualityComparer())
                            .ToList();