I am trying to learn the Linq/Lambda
expressions and was stuck at somewhere.
What I was Doing
I have created two classes with properties which have some common properties in them. The classes are like(It's test code).
class TestA
{
public int Id { get; set; }
public int ProductID { get; set; }
public string Category { get; set; }
public TestA(int id, int procid, string category)
{
this.Id = id;
this.ProductID = procid;
this.Category = category;
}
}
class TestB
{
public int ProductID { get; set; }
public string Category { get; set; }
public TestB(int procid, string category)
{
this.ProductID = procid;
this.Category = category;
}
}
Then I created the two list for them as,
List<TestA> testListA = new List<TestA>();
List<TestB> testListB = new List<TestB>();
TestA t1 = new TestA(1, 254, "ProductA");
TestA t2 = new TestA(1, 236, "ProductA");
TestA t3 = new TestA(1, 215, "ProductB");
TestA t4 = new TestA(1, 175, "ProductB");
TestA t5 = new TestA(1, 175, "ProductC");
testListA.Add(t1);
testListA.Add(t2);
testListA.Add(t3);
testListA.Add(t4);
testListA.Add(t5);
TestB tt1 = new TestB(254, "ProdcutA");
TestB tt2 = new TestB(215, "ProductB");
TestB tt3 = new TestB(175, "ProductC");
testListB.Add(tt3);
testListB.Add(tt2);
testListB.Add(tt1);
Now for result I wanted t2
as it's ProductID
match is not in the testListB
And t4
as it has matching ProductID
in testListB
but don't have the same Category
.
1) I need a List<A>
of every record which: No longer has a ProductID
held in the testListB
which I can get as ,
testListA.Select(x => x.ProductID).Except(testListB.Select(x => x.ProductID ));
2)No longer has a record which has a matching ProductID
and Category
in testListB
which I Can get using,
testListA.Where(a => testListB.Any(b => a.ProductID == b.ProductID && a.Category != b.Category));
**My Question **
Is it possible two make single linq expression to get result.I thought of using the implement IEqualityComparer
but I am not sure how to implement the GetHashCode
it for two different type of classes. So either combining the above query into single query or any other way to impliment custom Comparer
for two different Type of classes. Or is there any other simple way?
You have said that you need only these objects from testListA
:
ProductID
in testListB
ProductID
, but with different Category
So, your filter must be:
!testListB.Any(b => a.ProductID == b.ProductID && a.Category == b.Category)
So, change your code as:
testListA.Where(a => !testListB.Any(b => a.ProductID == b.ProductID && a.Category == b.Category));
Second approach:
Or you can create a new List<TestA>
from the second list:
var secondListA = testListB.Select(x=> new TestA(){Category=x.Category, ProductID=x.ProductID}).ToList();
And then create your Comparer
:
sealed class MyComparer : IEqualityComparer<TestA>
{
public bool Equals(TestA x, TestA y)
{
if (x == null)
return y == null;
else if (y == null)
return false;
else
return x.ProductID == y.ProductID && x.Category == y.Category;
}
public int GetHashCode(TestA obj)
{
return obj.ProductID.GetHashCode();
}
}
And use Except()
overload which produces the set difference of two sequences by using the specified IEqualityComparer<T>
to compare values.:
var result = testListA.Except(secondListA, new MyComparer ()).ToList();