Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a "not equal" in a linq join

Tags:

join

linq

equals

I am trying accomplish the LINQ query below but I need a "not equal" instead of equal, so that filteredEmployees has all employees from groupA minus groupB.

List<Employee> groupA = getEmployeeA(); List<Employee> groupB = getEmployeeB();          var filteredEmployees = from a in groupA                          join b in groupB on a.Name equals b.Name                         select a; 
like image 624
Robert Avatar asked Sep 21 '10 17:09

Robert


People also ask

How does join work in LINQ?

In a LINQ query expression, join operations are performed on object collections. Object collections cannot be "joined" in exactly the same way as two relational tables. In LINQ, explicit join clauses are only required when two source sequences are not tied by any relationship.

What type of join is LINQ join?

In LINQ, an inner join is used to serve a result which contains only those elements from the first data source that appears only one time in the second data source. And if an element of the first data source does not have matching elements, then it will not appear in the result data set.


2 Answers

You don't need a join for that:

var filteredEmployees = groupA.Except(groupB); 

Note that this will be a sequence of unique employees - so if there are any duplicates in groupA, they will only appear once in filteredEmployees. Of course, it also assumes you've got a reasonable equality comparer1. If you need to go specifically on name, you can use ExceptBy from MoreLINQ:

var filteredEmployees = groupA.ExceptBy(groupB, employee => employee.Name); 

Or without going into a third party library:

var groupBNames = new HashSet<string>(groupB.Select(x => x.Name)); var filteredEmployees = groupA.Where(x => !groupBNames.Contains(x.Name)); 

1 As pointed out in the comments, you can pass in an IEqualityComparer<T> as an argument to Except. I have a ProjectionEqualityComparer class in MiscUtil which makes it easy to build a comparer of the kind you need:

// I can't remember the exact method name, but it's like this :) var comparer = ProjectionEqualityComparer<Employee>.Create(x => x.Name); var filteredEmployees = groupA.Except(groupB, comparer); 
like image 150
Jon Skeet Avatar answered Sep 28 '22 08:09

Jon Skeet


No, a "not equal" operator would get you all combinations of groupA and groupB except the ones where the items were the same.

Using the Except method gets you what you want:

var filteredEmployees = groupA.Except(groupB); 
like image 24
Guffa Avatar answered Sep 28 '22 08:09

Guffa