設定作業 (C#)
LINQ 中的設定作業指的是產生結果集的查詢作業,而結果集是根據相同或不同集合內是否有對等項目而定。
重要
這些範例會使用 System.Collections.Generic.IEnumerable<T> 資料來源。 根據 System.Linq.IQueryProvider 的資料來源會使用 System.Linq.IQueryable<T> 資料來源和運算式樹狀架構。 運算式樹狀架構在允許的 C# 語法方面有限制。 此外,每個 IQueryProvider
資料來源 (例如 EF Core) 可能會施加更多限制。 檢查資料來源的文件。
方法名稱 | 描述 | C# 查詢運算式語法 | 其他相關資訊 |
---|---|---|---|
Distinct 或 DistinctBy |
移除集合中的重複值。 | 不適用。 | Enumerable.Distinct Enumerable.DistinctBy Queryable.Distinct Queryable.DistinctBy |
Except 或 ExceptBy |
傳回集差異,表示未出現在第二個集合中的某個集合中的項目。 | 不適用。 | Enumerable.Except Enumerable.ExceptBy Queryable.Except Queryable.ExceptBy |
Intersect 或 IntersectBy |
傳回集交集,表示出現在這兩個集合中的項目。 | 不適用。 | Enumerable.Intersect Enumerable.IntersectBy Queryable.Intersect Queryable.IntersectBy |
Union 或 UnionBy |
傳回集聯集,表示出現在兩個集合中任一集合的唯一項目。 | 不適用。 | Enumerable.Union Enumerable.UnionBy Queryable.Union Queryable.UnionBy |
Distinct
和 DistinctBy
下列範例說明一系列字串的 Enumerable.Distinct 方法行為。 所傳回的序列包含輸入序列中的唯一項目。
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
是 Distinct
的替代方法,其採用 keySelector
。 keySelector
作為來源類型的比較鑑別子。 在下列程式碼中,會根據 Length
區分字詞,並顯示每個長度的第一個字詞:
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
和 ExceptBy
下列範例會說明 Enumerable.Except 的行為。 所傳回的序列只包含第一個輸入序列中不在第二個輸入序列中的項目。
注意
本文中的下列範例會使用此區域的通用數據源。
每個 Student
都有一個等級、一個主要部門和一系列分數。 Teacher
也有一個 City
屬性,可識別教師持有課程的校園。 Department
具有名稱,以及擔任部門負責人 Teacher
的參考。
您可以在來源存放庫中找到範例數據集。
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
*/
ExceptBy 方法為 Except
的替代方法,其採用兩個可能異質類型的序列和 keySelector
。 keySelector
與第一個集合的類型相同。 請考慮排除下列 Teacher
陣列和教師識別碼。 若要在第一個集合中尋找不在第二個集合中的教師,您可以將教師識別碼投影到第二個集合:
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}");
}
在上述 C# 程式碼中:
- 陣列
teachers
只會篩選不在teachersToExclude
陣列中的教師。 teachersToExclude
陣列包含所有部門負責人的ID
值。- 呼叫
ExceptBy
會產生寫入主控台的一組新值。
新值的集合類型為 Teacher
,這是第一個集合的類型。 teachers
陣列中的每個 teacher
如果在 teachersToExclude
陣列中沒有對應的識別碼值,就會寫入主控台。
Intersect
和 IntersectBy
下列範例會說明 Enumerable.Intersect 的行為。 所傳回的序列包含兩個輸入序列共有的項目。
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
*/
IntersectBy 方法為 Intersect
的替代方法,其採用兩個可能異質類型的序列和 keySelector
。 keySelector
可作為第二個集合類型的比較鑑別子。 請考慮下列學生和教師陣列。 查詢會依名稱比對每個序列中的專案,以尋找同時為教師的學生:
foreach (Student person in
students.IntersectBy(
teachers.Select(t => (t.First, t.Last)), s => (s.FirstName, s.LastName)))
{
Console.WriteLine($"{person.FirstName} {person.LastName}");
}
在上述 C# 程式碼中:
- 查詢會藉由比較名稱來得出
Teacher
和Student
的交集。 - 只有在這兩個陣列中都能找到的人員才會出現在產生的序列中。
- 產生的
Student
執行個體會寫入主控台。
Union
和 UnionBy
下列範例說明兩個字串序列的聯合作業。 所傳回的序列包含兩個輸入序列中的唯一項目。
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
*/
UnionBy 方法為 Union
的替代方法,其採用兩個相同類型序列和 keySelector
。 keySelector
作為來源類型的比較鑑別子。 下列查詢會產生學生或教師的所有人員清單。 同樣是教師的學生只能加入到聯合一次:
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}");
}
在上述 C# 程式碼中:
teachers
和students
陣列會使用其名稱作為索引鍵選取器編織在一起。- 產生的名稱會寫入主控台。