7

i think this question has been asked before but i havent been able to deduce a clear answer. I am trying to find the best way (or a way) to intersect two completely different ienumerable collections.

class A:

  • int z1
  • int z2
  • int z3
  • string z4

class B:

  • int j5
  • int j6
  • T j7
  • T j8
  • string j9

..I want to intersect List<A> with List<B> on z2 == j6.

can this be done?

Gabe
  • 84,912
  • 12
  • 139
  • 238
Grant
  • 11,138
  • 32
  • 94
  • 140
  • 3
    Are you *sure* you want to find an intersection? It sounds to me like you want a *join*. – Gabe Mar 29 '11 at 06:32
  • Similar question: [Intersect a collection of collections in LINQ](http://stackoverflow.com/questions/2532003/intersect-a-collection-of-collections-in-linq) – Devendra D. Chavan Mar 29 '11 at 06:40

4 Answers4

27

The question doesn't really make sense - what would the result type be? Intersections have to be performed on two sequences of the same type. It sounds like you don't so much want an intersection between two sets, as a filter of the first sequence based on possible values of z2. For example:

HashSet<int> validZ2 = new HashSet<int>(listB.Select(x => x.j6));
var filtered = listA.Where(x => validZ2.Contains(x.z2));

Or possibly as Gabe suggests, you want a join. For example:

var query = from a in listA
            join b in listB on a.z2 equals b.j6
            select new { a, b };

That will give you all pairings of values from the two lists which match on z2/j6.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    I think that OP actually may want a join. – Gabe Mar 29 '11 at 06:44
  • @Gabe: It's hard to say, to be honest. It's possible - I'll edit in case. It's not really an intersection as such though... – Jon Skeet Mar 29 '11 at 06:49
  • My guess is that the OP has been unable to make sense of other answers because they are using the wrong terminology. As you say, intersection doesn't make sense on different data types. If you reinterpret "intersection" to just be "find matching values", though, "join" also fits the definition. Since joins do make sense for different data types, I figured that's more likely to be what OP wants. – Gabe Mar 29 '11 at 06:53
  • thankyou.. you are correct. i actually wanted to filter the results of the first sequence. thanks - used a join! – Grant Mar 29 '11 at 08:21
2

You need to implement a custom equality comparer (see IEqualityComparer<T> interface) to pass it as a second argument to Intersect().

UserControl
  • 14,766
  • 20
  • 100
  • 187
1

By using the intersect method, you can get common members between the two enumerables, like this example demonstrates:

[Test]
public void TestObjectIntersect()
{
    var a = new List<object> { 1, 2, 3, "test", "test2" };
    var b = new List<object> { 4, 5, 1, "test2" };
    var c = a.Intersect(b);
    Console.WriteLine(String.Join(",", c.Select(x => x.ToString()).ToArray()));
}
Ioannis Karadimas
  • 7,746
  • 3
  • 35
  • 45
0
class Program
{

    static void Main(string[] args)
    {
        var aList = (from item in Enumerable.Range(1, 10)
                        select new A { Z1 = item, Z2 = item * 2 }).ToList();

        var bList = (from item in Enumerable.Range(10, 100)
                     select new B { J5 = item, J6 = item / 2 }).ToList();

        var intersect = (from a in aList
                         join b in bList
                            on a.Z2 equals b.J6
                         select new { A = a, B = b }).ToList();

        foreach (var item in intersect)
        {
            Console.WriteLine("A:{{{0}}}, B:{{{1}}}", item.A, item.B);
        }
    }
}

public class A
{
    public int Z1 { get; set; }

    public int Z2 { get; set; }

    // other fields and properties

    public override string ToString()
    {
        return string.Format("Z1={0}, Z2={1}", Z1, Z2);
    }
}

public class B
{
    public int J5 { get; set; }

    public int J6 { get; set; }

    // other fields and properties

    public override string ToString()
    {
        return string.Format("J5={0}, J6={1}", J5, J6);
    }
}
Gabe
  • 84,912
  • 12
  • 139
  • 238
Yuriy Rozhovetskiy
  • 22,270
  • 4
  • 37
  • 68