tags:

views:

175

answers:

2

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;
+11  A: 

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);
Jon Skeet
Note to @Robert: You can provide an `IEqualityComparer<Employee>` implementation for an overload of `Except`. Useful if overriding Equals/GetHashCode is either (a) impossible or (b) undesirable.
Anthony Pegram
@Jon. Thanks. The 3rd option you wrote did the trick. I tried the IEqualityComparer before and it did not work.
Robert
I love the hashset method without the 3rd party. It's pretty slick.
A_Var
+1  A: 

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);
Guffa