web-dev-qa-db-fra.com

Y a-t-il un "différent" dans une jointure linq

J'essaie d'accomplir la requête LINQ ci-dessous mais j'ai besoin d'un "différent" au lieu d'être égal, de sorte que les employés filtrés aient tous les employés du groupe A moins le groupe B.

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;
29
Robert

Vous n'avez pas besoin d'une jointure pour cela:

var filteredEmployees = groupA.Except(groupB);

Notez que ce sera une séquence d'employés uniques - donc s'il y a des doublons dans groupA, ils n'apparaîtront qu'une seule fois dans filteredEmployees. Bien sûr, cela suppose également que vous avez un comparateur d'égalité raisonnable1. Si vous devez aller spécifiquement sur le nom, vous pouvez utiliser ExceptBy from MoreLINQ :

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

Ou sans entrer dans une bibliothèque tierce:

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

1 Comme indiqué dans les commentaires, vous pouvez passer un IEqualityComparer<T> comme argument pour Except. J'ai une classe ProjectionEqualityComparer dans MiscUtil qui facilite la construction d'un comparateur du type dont vous avez besoin:

// 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);
53
Jon Skeet

Non, un opérateur "différent" vous obtiendrait toutes les combinaisons de groupe A et de groupe B, sauf celles où les éléments étaient les mêmes.

L'utilisation de la méthode Except vous permet d'obtenir ce que vous voulez:

var filteredEmployees = groupA.Except(groupB);
4
Guffa

Dans Entity Framework 6, j'ai obtenu de meilleurs résultats en utilisant

var filteredEmployees = groupA.Where(a => !groupB.Select(b => b.Name).Contains(a.Name));
3
mcandal

utilisation de ce code pour réduire le coût du serveur:

Le code fonctionne très rapidement par rapport à d'autres codes

        var noExistList = (from n in groupA 
                                join o in groupA  on n.Id equals o.Id into p
                                where p.Count() == 0
                                select n).ToList();

remarque: groupA est une nouvelle liste à ajouter.

0
FatalMan