比较两个列表的Linq语法

本文关键字:列表 Linq 语法 两个 比较 | 更新日期: 2023-09-27 18:02:26

我有两个自定义类型对象列表

List<Obj> list1;
List<Obj> list2;
class Obj
{
  public List<X> xlist;
  public List<Y> Ylist;
  public bool mybool;
}
class X
{
   int x;
   float y;
}

class Y
{
   sting str;
   bool  y;
}

我想比较list1和list2中的每个成员是否具有相等的值。

比较两个列表的Linq语法

您必须有意义地覆盖EqualsGetHashCode。您还可以为LINQ方法(如SequenceEqualExcept)实现IEquatable<Obj>或使用自定义IEqualityComparer<Obj>。例如:

public class Obj:  IEquatable<Obj>
{
    public List<X> xlist;
    public List<Y> Ylist;
    public bool mybool;

    public bool Equals(Obj other)
    {
        if (other == null) return false;
        if(object.ReferenceEquals(this, other)) return true;
        if (mybool != other.mybool) return false;
        return xlist.SequenceEqual(other.xlist) && Ylist.SequenceEqual(other.Ylist);
    }
    public override bool Equals(object obj)
    {
        return base.Equals(obj);
    }
    public override int GetHashCode()
    {
        unchecked
        {
            int hash = mybool ? 13 : 19;
            foreach (X x in xlist)
            {
                hash = hash * 31 + x.GetHashCode();
            }
            foreach (Y y in Ylist)
            {
                hash = hash * 31 + y.GetHashCode();
            }
            return hash;
        }
    }
}
public class X: IEquatable<X>
{
    public int x;
    public float y;
    public bool Equals(X other)
    {
        if (other == null) return false;
        if (object.ReferenceEquals(this, other)) return true;
        return x == other.x && y == other.y;
    }
    public override bool Equals(object obj)
    {
        var other = obj as X;
        if (other == null) return false;
        return this.Equals(other);
    }
    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 19;
            hash = hash * 31 + x;
            hash = hash * 31 + (int)y;
            return hash;
        }
    }
}

public class Y : IEquatable<Y>
{
    public string str;
    public bool y;
    public bool Equals(Y other)
    {
        if (other == null) return false;
        if (object.ReferenceEquals(this, other)) return true;
        return str == other.str && y == other.y;
    }
    public override bool Equals(object obj)
    {
        var other = obj as Y;
        if (other == null) return false;
        return this.Equals(other);
    }
    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 19;
            hash = hash * 31 + (str == null ? 0 : str.GetHashCode());
            hash = hash * 31 + (y ? 1 : 0);
            return hash;
        }
    }
}

现在你可以用SequenceEqual代替List<Obj>:

bool sameItemsSameOrder = list1.SequenceEqual(list2);  // finally you got your one-liner

有扩展方法SequenceEqual。"通过使用默认的类型相等比较器比较元素来确定两个序列是否相等",并使用带有自己的相等比较器的重载。

var areEqual = list1.SequenceEqual(list2);

默认情况下,它调用列表中对象的Equals方法,因此请确保它按照您的需要执行或传递您自己的相等比较器。

Linq是一个查询语法。例如,你需要Linq在一个列表中查找不在另一个列表中的项。比较序列与SequenceEqual不是一个查询和IMHO不是真正的Linq。然而,这有关系吗?