4

In the below code if I iterated over L3 I would expect to have 2 results available. However it only has one result and that result is the objTest with a Id = 9. I thought it should be a result set with two objtest s' Id = 9 and Id = 10.

class Program
{
public class objTest 
{
    public int Value { get; set; }
    public bool On  { get; set; }
    public int Id { get; set; }
}
class PramComp : EqualityComparer<objTest>
{
    public override bool Equals(objTest x, objTest y)
    {
        return x.Value == y.Value;
    }
    public override int GetHashCode(objTest obj)
    {
        return obj.Value.GetHashCode();
    }
}
 static void Main(string[] args)
{
    List<objTest> L1 = new List<objTest>();
    L1.Add(new objTest { Value = 1, On = true ,Id =1});
    L1.Add(new objTest { Value = 2, On = false ,Id =2});
    L1.Add(new objTest { Value = 3, On = false, Id = 3 });
    L1.Add(new objTest { Value = 4, On = false ,Id =4});
    L1.Add(new objTest { Value = 5, On = false ,Id =5});

    List<objTest> L2 = new List<objTest>();
    L2.Add(new objTest { Value = 6, On = false ,Id =6});
    L2.Add(new objTest { Value = 7, On = false ,Id=7});
    L2.Add(new objTest { Value = 8, On = false,Id =8 });
    L2.Add(new objTest { Value = 1, On = true,Id =9 });
    L2.Add(new objTest { Value = 1, On = true, Id =10 });

    var L3 = L2.Intersect(L1, new PramComp());

}
}

So I have made a mistake with my code if I want to return the two results Id=9 and Id=10. Could someone tell me where my mistake is?

Paul Stanley
  • 1,999
  • 1
  • 22
  • 60

3 Answers3

8

Enumerable.Intersect is designed to produce:

the set intersection of two sequences.

A "set" does not allow duplicate values, which means you'll only get one of the two values.

If you want to return both of the ones that match, you could use:

var L3 = L2.Where(item => L1.Any(one => one.Value == item.Value));

This will go through the L2 collection and find all items which have any matching value in L1, but preserve the duplicates.

Servy
  • 202,030
  • 26
  • 332
  • 449
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
3

As an aside, Reed Copsey already pointed out where your incorrect assumption lies. However, his way of linking two lists is inefficient. join forms dictioanry to pair the elements so it is better to use it:

var l3 = from e2 in L2
         join e1 in L1 on e1.Value equals e2.Value
         into grp
         where grp.Any()
         select e2;
Alireza
  • 10,237
  • 6
  • 43
  • 59
  • Yes but should be 'on e1.Value equals e2.Value' does the trick – Paul Stanley Oct 02 '13 at 20:55
  • This doesn't produce the desired results. If there were duplicate items in `L1` matching at least one item in `L2` the items in `L2` would be duplicated. This would then spit out the value multilpe times when it shouldn't. You need to use a `GroupJoin` rather than a `Join`, and where there is at least a match, to produce the correct results. – Servy Oct 02 '13 at 20:58
  • @Servy You are right. I amended the answer. Thank you for correcting me. – Alireza Oct 03 '13 at 07:25
0

Your equality comparer compares the Value property why id 9 and id 10 are considered the same element for the intersection. Thus there is only one element in common.

faester
  • 14,886
  • 5
  • 45
  • 56