Overview
Set operations are query operations that produce a result set that is based on the presence or absence of equivalent elements within the same or separate sets.
Methods
Method | Description | Query expression |
---|---|---|
Distinct(By) | Removes duplicate values from a collection | N/A |
Except(By) | Returns the elements of one collection that do not appear in the other | N/A |
Intersect(By) | Elements that appear in each of two collections | N/A |
Union(By) | Unique elements that appear in either of two collections | N/A |
The *By
methods take a keySelector
which is used as the comparative discriminator of the source type.
Distinct
and DistinctBy
These methods both take a single collection.
Distinct
returns the unique elements in a collection:
string[] words = ["the", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"];
IEnumerable<string> query = from word in words.Distinct()
select word;
DistinctBy
, like all *By
methods, takes a keySelector
which is used as the comparative discriminator of the source type.
In this example, the first word of each length is displayed:
foreach (string word in words.DistinctBy(p => p.Length))
Console.WriteLine(word);
Except
and ExceptBy
These methods both take two collections.
Except
returns only the elements from the first collection that are not present in the second:
string[] words1 = ["the", "quick", "brown", "fox"];
string[] words2 = ["jumped", "over", "the", "lazy", "dog"];
IEnumerable<string> query = from word in words1.Except(words2)
select word;
ExceptBy
’s keySelector
is of the same type as the first collection’s type.
To find teachers in the first collection that are not in the second collection, project the teacher’s ID onto the second 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}");
Intersect
and IntersectBy
These methods both take two collections.
Intersect
returns a collection of elements that are common to both input collections:
string[] words1 = ["the", "quick", "brown", "fox"];
string[] words2 = ["jumped", "over", "the", "lazy", "dog"];
IEnumerable<string> query = from word in words1.Intersect(words2)
select word;
IntersectBy
’s keySelector
is used as the comparative discriminator of the second collection’s type:
foreach (Student person in students.IntersectBy(
teachers.Select(t => (t.First, t.Last)), s => (s.FirstName, s.LastName)))
{
Console.WriteLine($"{person.FirstName} {person.LastName}");
}
Union
and UnionBy
These methods both take two collections.
Union
returns a collection that contains the unique elements from both input collections:
string[] words1 = ["the", "quick", "brown", "fox"];
string[] words2 = ["jumped", "over", "the", "lazy", "dog"];
IEnumerable<string> query = from word in words1.Union(words2)
select word;
UnionBy
’s keySelector
is used as the comparative discriminator of the source collection’s type:
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}");
}