Getting the difference between two lists based on specific fields

I am new to LINQ and I may have painted myself on the corner. I have two lists (left and right), and I need:

a) Get relevant items based on specific fields

b) Get items on the left without matching on the right

c) Get items on the right that do not match on the left

A match is found if certain fields are equal. Other fields may or may not contain values, but should not affect match comparisons.

To get the element a, I did a JOIN on both lists:

 var q = from a in r1 from b in r2 where a.Prop1 == b.Prop1 && a.Prop3 == b.Prop3 select new { a.Prop1, a.Prop2, b.Prop3 }; 

I'm not sure where to go from here. I think I can not use .Except() , because the other properties for both lists will be different and may lead to a breakdown of the comparison.

I also tried using Left Join and getting elements without matches:

  var q = from c in r1 join p in r2 on c.Prop1 equals p.Prop1 into cp from p in cp.DefaultIfEmpty() select new { Prop1 = c.Prop1, Prop2 = p == null ? "N/A" : p.Prop2 }; 

however, I found that you cannot compare more than one field for comparison.

Do you have multiple fields on Left Join with LINQ? Are there other ways (other than LINQ) to get the difference between the two lists?

+4
source share
3 answers

Intersect and Except (similar to Cuong Le solution):

 public class MyComparer : IEqualityComparer<YourClass> { #region IEqualityComparer<YourClass> Members public bool Equals(YourClass x, YourClass y) { return x.Prop1.Equals(y.Prop1) && x.Prop3.Equals(y.Prop3); } public int GetHashCode(YourClass obj) { int hCode = obj.Prop1.GetHashCode() ^ obj.Prop3.GetHashCode(); return hCode.GetHashCode(); } #endregion } // matched elements from both lists var r1 = l1.Intersect<YourClass>(l2, new MyComparer()); // elements from l1 not in l2 var r2 = l1.Except<YourClass>(l2, new MyComparer()); // elements from l2 not in l1 var r3 = l2.Except<YourClass>(l1, new MyComparer()); 
+4
source

By default, the Except method uses EqualityComparer.Default , so you cannot use it if you have objects with different property values

But you can use a different overload method except for setting EqualityComparer<T> , suppose it ignores Pro3

 public class CustomComparer : EqualityComparer<A> { public override int GetHashCode(A a) { int hCode = a.Pro1.GetHashCode() ^ a.Pro2.GetHashCode(); return hCode.GetHashCode(); } public override bool Equals(A a1, A a2) { return a1.Pro1.Equals(a2.Pro1) && a1.Pro2.Equals(a2.Pro2) } } 

Then you can use Except :

 listA.Except(listB, new CustomComparer()); 
+2
source

What about

a)

 r1.Where(x=>r2.Any(y=>x.Prop1==y.Prop1&&x.Prop3==y.Prop3)) .Select(x=>new { x.Prop1,x.Prop2,x.Prop3}); 

b)

 r1.Where(x=>!r2.Any(y=>x.Prop1==y.Prop1&&x.Prop3==y.Prop3)) .Select(x=>new { x.Prop1,x.Prop2,x.Prop3}); 

with)

 r2.Where(x=>!r1.Any(y=>x.Prop1==y.Prop1&&x.Prop3==y.Prop3)) .Select(x=>new { x.Prop1,x.Prop2,x.Prop3}); 
0
source

Source: https://habr.com/ru/post/1436329/


All Articles