Opérations ensemblistes (C#)
Les opérations ensemblistes dans LINQ font référence à des opérations de requête qui produisent un jeu de résultats basé sur la présence ou l’absence d’éléments équivalents dans les mêmes collections ou dans des collections distinctes.
Important
Ces exemples utilisent une source de données System.Collections.Generic.IEnumerable<T>. Les sources de données basées sur System.Linq.IQueryProvider utilisent des sources de données System.Linq.IQueryable<T> et des arborescences d’expressions. Les arborescences d’expressions présentent des limitations sur la syntaxe C# autorisée. De plus, chaque source de données IQueryProvider
, telle que EF Core peut imposer des restrictions supplémentaires. Consultez la documentation de votre source de données.
Noms des méthodes | Description | Syntaxe d'expression de requête C# | Plus d’informations |
---|---|---|---|
Distinct ou DistinctBy |
Supprime les valeurs en double d’une collection. | Non applicable. | Enumerable.Distinct Enumerable.DistinctBy Queryable.Distinct Queryable.DistinctBy |
Except ou ExceptBy |
Retourne la différence ensembliste, à savoir les éléments d’une collection qui n’apparaissent pas dans une seconde collection. | Non applicable. | Enumerable.Except Enumerable.ExceptBy Queryable.Except Queryable.ExceptBy |
Intersect ou IntersectBy |
Retourne l’intersection ensembliste, à savoir les éléments qui apparaissent dans chacune des deux collections. | Non applicable. | Enumerable.Intersect Enumerable.IntersectBy Queryable.Intersect Queryable.IntersectBy |
Union ou UnionBy |
Retourne l’union ensembliste, à savoir les éléments uniques qui apparaissent dans l’une ou l’autre des deux collections. | Non applicable. | Enumerable.Union Enumerable.UnionBy Queryable.Union Queryable.UnionBy |
Distinct
et DistinctBy
L’exemple suivant illustre le comportement de la méthode Enumerable.Distinct sur une séquence de chaînes. La séquence retournée contient les éléments uniques de la séquence d’entrée.
string[] words = ["the", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"];
IEnumerable<string> query = from word in words.Distinct()
select word;
foreach (var str in query)
{
Console.WriteLine(str);
}
/* This code produces the following output:
*
* the
* quick
* brown
* fox
* jumped
* over
* lazy
* dog
*/
DistinctBy
est une approche alternative à Distinct
qui prend un keySelector
. keySelector
est utilisé comme discriminateur comparatif du type source. Dans le code suivant, les mots sont discriminés en fonction de leur Length
, et le premier mot de chaque longueur est affiché :
string[] words = ["the", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"];
foreach (string word in words.DistinctBy(p => p.Length))
{
Console.WriteLine(word);
}
// This code produces the following output:
// the
// quick
// jumped
// over
Except
et ExceptBy
L’exemple suivant illustre le comportement de Enumerable.Except. La séquence retournée contient uniquement les éléments de la première séquence d’entrée qui ne figurent pas dans la seconde séquence d’entrée.
Remarque
Les exemples suivants de cet article utilisent les sources de données courantes pour cette zone.
Chaque Student
a un niveau scolaire, un département principal et une série de notes. Un Teacher
a également une propriété City
qui identifie le campus où l’enseignant donne des cours. Un Department
a un nom, et une référence à un Teacher
qui est responsable du département.
Vous trouverez l’exemple de jeu de données dans le référentiel source.
public enum GradeLevel
{
FirstYear = 1,
SecondYear,
ThirdYear,
FourthYear
};
public class Student
{
public required string FirstName { get; init; }
public required string LastName { get; init; }
public required int ID { get; init; }
public required GradeLevel Year { get; init; }
public required List<int> Scores { get; init; }
public required int DepartmentID { get; init; }
}
public class Teacher
{
public required string First { get; init; }
public required string Last { get; init; }
public required int ID { get; init; }
public required string City { get; init; }
}
public class Department
{
public required string Name { get; init; }
public int ID { get; init; }
public required int TeacherID { get; init; }
}
string[] words1 = ["the", "quick", "brown", "fox"];
string[] words2 = ["jumped", "over", "the", "lazy", "dog"];
IEnumerable<string> query = from word in words1.Except(words2)
select word;
foreach (var str in query)
{
Console.WriteLine(str);
}
/* This code produces the following output:
*
* quick
* brown
* fox
*/
La méthode ExceptBy est une approche alternative à Except
qui prend deux séquences de types potentiellement hétérogènes et un keySelector
. Le keySelector
est du même type que le type de la première collection. Considérez le tableau Teacher
suivant et les ID d’enseignant à exclure. Pour rechercher des enseignants dans la première collection qui ne figurent pas dans la deuxième collection, vous pouvez projeter l’ID de l’enseignant sur la seconde collection :
int[] teachersToExclude =
[
901, // English
965, // Mathematics
932, // Engineering
945, // Economics
987, // Physics
901 // Chemistry
];
foreach (Teacher teacher in
teachers.ExceptBy(
teachersToExclude, teacher => teacher.ID))
{
Console.WriteLine($"{teacher.First} {teacher.Last}");
}
Dans le code C# précédent :
- Le tableau
teachers
est filtré de façon à contenir seulement les enseignants qui ne figurent pas dans le tableauteachersToExclude
. - Le tableau
teachersToExclude
contient la valeur de l’ID
de tous les responsables de département. - L’appel à
ExceptBy
entraîne un nouvel ensemble de valeurs qui sont écrites dans la console.
Le nouvel ensemble de valeurs est de type Teacher
, qui est le type de la première collection. Chaque teacher
du tableau teachers
qui n’a pas de valeur d’ID correspondante dans le tableau teachersToExclude
est écrit sur la console.
Intersect
et IntersectBy
L’exemple suivant illustre le comportement de Enumerable.Intersect. La séquence retournée contient les éléments qui sont communs aux deux séquences d’entrée.
string[] words1 = ["the", "quick", "brown", "fox"];
string[] words2 = ["jumped", "over", "the", "lazy", "dog"];
IEnumerable<string> query = from word in words1.Intersect(words2)
select word;
foreach (var str in query)
{
Console.WriteLine(str);
}
/* This code produces the following output:
*
* the
*/
La méthode IntersectBy est une approche alternative à Intersect
qui prend deux séquences de types potentiellement hétérogènes et un keySelector
. keySelector
est utilisé comme discriminateur comparatif du type de la deuxième collection. Considérez les tableaux d’étudiants et d’enseignants suivants. La requête correspond aux éléments de chaque séquence par nom pour rechercher les étudiants qui sont également enseignants :
foreach (Student person in
students.IntersectBy(
teachers.Select(t => (t.First, t.Last)), s => (s.FirstName, s.LastName)))
{
Console.WriteLine($"{person.FirstName} {person.LastName}");
}
Dans le code C# précédent :
- La requête produit l’intersection de
Teacher
et deStudent
en comparant les noms. - Seules les personnes qui se trouvent dans les deux tableaux sont présentes dans la séquence résultante.
- Les instances
Student
résultantes sont écrites dans la console.
Union
et UnionBy
L’exemple suivant illustre une opération d’union sur deux séquences de chaînes. La séquence retournée contient les éléments uniques des deux séquences d’entrée.
string[] words1 = ["the", "quick", "brown", "fox"];
string[] words2 = ["jumped", "over", "the", "lazy", "dog"];
IEnumerable<string> query = from word in words1.Union(words2)
select word;
foreach (var str in query)
{
Console.WriteLine(str);
}
/* This code produces the following output:
*
* the
* quick
* brown
* fox
* jumped
* over
* lazy
* dog
*/
La méthode UnionBy est une approche alternative à Union
qui prend deux séquences du même type et un keySelector
. keySelector
est utilisé comme discriminateur comparatif du type source. La requête suivante produit la liste de toutes les personnes qui sont des étudiants ou des enseignants. Les étudiants qui sont également enseignants sont ajoutés à l’union ensembliste une seule fois :
foreach (var person in
students.Select(s => (s.FirstName, s.LastName)).UnionBy(
teachers.Select(t => (FirstName: t.First, LastName: t.Last)), s => (s.FirstName, s.LastName)))
{
Console.WriteLine($"{person.FirstName} {person.LastName}");
}
Dans le code C# précédent :
- Les tableaux
teachers
etstudents
sont rapprochés en utilisant les noms comme sélecteur de clé. - Les noms résultants sont écrits sur la console.