Argon
Argon

Reputation: 149

Intersect between 2 collections in C#

I have:

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

And I need to intersect it comparing ids. Something like that:

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

But I don't know which method I must use and it sintax.

I found this:

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

But this return a list of ids and i need a list of elements contained in both lists.

Thank you!

Upvotes: 2

Views: 1739

Answers (3)

Farhad Jabiyev
Farhad Jabiyev

Reputation: 26635

The other answers are correct, but you can use Intersect with your custom comparer. You can create custom comparer by implementing IEqualityComparer<> interface. And for implementing this interface we must implmenet two methods, Equals and GetHashCode.

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;    
        }
    }
}

And then:

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

You can also use this comparer in Except method, for finding the difference of two sequences.

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

Additionally:

From the first point of view you may misunderstood GetHashCode(). You can read about this method in many question of StackOverflow. You can read the answer to this question.

Upvotes: 1

Tim Schmelter
Tim Schmelter

Reputation: 460068

I would use 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();

If you would override Equals + GetHashCode in INFRAESTRUCTURA or provide a custom IEqualityComparer<INFRAESTRUCTURA> you could use Enumerable.Intersect directly:

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

Here's a possible implementation:

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;
    }
}

you can use the overloads which take an IEqualityComparer<T> like here:

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

If you want both objects in the result you could use an anonymous type:

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

Upvotes: 2

wertzui
wertzui

Reputation: 5720

You can use Linq Join

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

Upvotes: 1

Related Questions