Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq and Contains

Tags:

c#

contains

linq

First example which works:

public class Test
{
    public int ID;
    public string Name;
}

List<int> list1 = Load1();
List<Test> list2 = Load2();

var query = list2.Where(c => list1.Contains(c.ID));

Now I would like to use two lists of objects as a source and get list of objects that have this same values for member ID.

List<Test> list1 = Load2();
List<Test> list2 = Load2();

Below doesn't compile:

var query = list2.Where(c => **list1.ID.Contains**(c.ID));

I know it is wrong but placed it here for better understanding. I would appreciate someone to show me the right path :-)

Regards Mariusz

like image 733
Mariusz Avatar asked Aug 25 '11 21:08

Mariusz


4 Answers

You can perform an inner join as follows:

var query = from x in list1
            join y in list2 on x.ID equals y.ID
            select new { x, y };

or

var query = list1.Join(list2,
                       x => x.ID,
                       y => y.ID,
                       (x, y) => new { x, y });
like image 58
dtb Avatar answered Oct 04 '22 23:10

dtb


You could make your Test class equatable:

public class Test : IEquatable<Test>
{
  public int Id {get;set;}
  public bool Equals(Test other)
  {
    return this.Id == other.Id;
  }
}

Then this would work:

list1.Where(item => list2.Contains(item));
like image 21
scottm Avatar answered Oct 04 '22 21:10

scottm


Try

list2.Where(c => list1.Any(d => d.ID == c.ID)); 

You need to enumerate the other collection with your own code to get what you want, because .Contains uses the .Equals function, which for Objects will just match against the reference.

like image 34
Michael Yoon Avatar answered Oct 04 '22 21:10

Michael Yoon


enter code heresimple version would be

var query = list2.Where(c=> list1.Select(l=>l.ID).Contains(c.ID))

or you could use the linq version of an inner join if you have no repetition

var query = list2.Join(list1,a=>a.ID,b=>b.ID,(a,b)=>a);

or you could use a System.Collections.Generic.IEQualityComparer

public class TestComparerer : IEqualityComparer<Test> {
    bool IEqualityComparer<Test>.Equals(Test a, Test b) {
        return a!=null && b!=null && a.ID.Equals(b.ID);
    }

    int IEqualityComparer<Test>.GetHashCode(Test a){
     return a.ID.GetHashCode();
    }
}

var query = list2.intersect(list1,new TestComparer());

finally if you override Equals and GetHashCode() on test you can make them comparable

public override bool Equals(object o) {
var other=o as Test;
return other!=null && this.ID==other.ID;
}

public override int GetHashCode() {
return ID.GetHashCode();
}

again this will allow you to do list1.Intersect(list2) or list2.Intersect(list1)

like image 45
Bob Vale Avatar answered Oct 04 '22 23:10

Bob Vale