在 C# 中的 2 个集合之间相交

Intersect between 2 collections in C#

我有:

            List<INFRAESTRUCTURA> l1 = listQ1.ToList();
            List<INFRAESTRUCTURA> l2 = listQ2.ToList();

而且我需要比较 id 将其相交。类似的东西:

 l1.Intersect(l2, l1[].id_infraestructura == l2[].id_infraestructura) 

但我不知道我必须使用哪种方法和语法。

我发现了这个:

var ids = list1.Select(a => a.id).Intersect(list2.Select(b => b.id));

但是这个 return 一个 id 列表,我需要一个包含在两个列表中的元素列表。

谢谢!

您可以使用 Linq Join

l1.Join(l2, l => l.id_infraestructura, r => r.id_infraestructura, (l,r) => l.id_infraestructura);

我会使用 Enumerable.Join:

var intersecting = from i1 in l1
                   join i2 in l2
                   on i1.id_infraestructura equals i2.id_infraestructura
                   select i1;
List<INFRAESTRUCTURA> result = intersecting.ToList();

如果您要覆盖 INFRAESTRUCTURA 中的 Equals + GetHashCode 或提供自定义 IEqualityComparer<INFRAESTRUCTURA>,您可以直接使用 Enumerable.Intersect

List<INFRAESTRUCTURA> result = l1.Intersect(l2).ToList();

这是一个可能的实现:

public class InfrastructureComparer : IEqualityComparer<INFRAESTRUCTURA>
{
    public bool Equals(INFRAESTRUCTURA x, INFRAESTRUCTURA y)
    {
        if (x == null && y == null) return true;
        if (x == null || y == null) return false;
        return x.id_infraestructura == y.id_infraestructura;
    }

    public int GetHashCode(INFRAESTRUCTURA obj)
    {
        if (obj == null) return 0;
        return obj.id_infraestructura;
    }
}

您可以使用带有 IEqualityComparer<T> 的重载,如下所示:

List<INFRAESTRUCTURA> result = l1.Intersect(l2, new InfrastructureComparer()).ToList();

如果您想要结果中的两个对象,您可以使用匿名类型:

var intersecting = from i1 in l1
                   join i2 in l2
                   on i1.id_infraestructura equals i2.id_infraestructura
                   select new { i1, i2 };

其他答案是正确的,但您可以将 Intersect 与您的自定义比较器一起使用。您可以通过实现 IEqualityComparer<> 接口来创建自定义比较器。为了实现这个接口,我们必须实现两个方法,EqualsGetHashCode

public class InfraestructuraComparer: IEqualityComparer<INFRAESTRUCTURA>
{
    /// <summary>
    /// Whether the two INFRAESTRUCTURA are equal.
    /// </summary>
    public bool Equals(INFRAESTRUCTURA firstObj, INFRAESTRUCTURA secondObj)
    {
        if (firstObj == null && secondObj == null)
            return true;

        if (firstObj == null || secondObj == null)
            return false;

        // Your equality logic goes to here
        return firstObj.ID == secondObj.ID;
    }

    /// <summary>
    /// Return the hash code for this instance.
    /// </summary>
    public int GetHashCode(INFRAESTRUCTURA obj)
    {
        // Don't compute hash code on null object.
        if (obj == null) return 0;

        unchecked
        {
            var hash = 17;

            hash = hash * 23 + obj.Id.GetHashCode();

            return hash;    
        }
    }
}

然后:

var result = list1.Intersect(list2, new InfraestructuraComparer());

您也可以在 Except 方法中使用此比较器,以查找两个序列的差异。

var result = list1.Except(list2, new InfraestructuraComparer());

另外:

从第一个角度看你可能误解了GetHashCode()。您可以在 Whosebug 的许多问题中了解此方法。你可以阅读这个问题的answer