LINQ聯接函數

摘要:這五種LINQ函數聯接序列的方法非常奇妙,希望各位.NET程序員能掌握,並在實際開發中運用上。

  今天我們來看看5種使用Linq函數聯接序列的方法,這5種方法可以歸入下列兩類:

  同類的聯接

  Concat()

  Union()

  不同類的聯接

  Zip()

  Join()

  GroupJoin()

  Concat() – 串聯序列

  最簡單的序列合併,concat僅僅是將第二個序列接在第一個序列後面, 注意:返回的序列並沒有改變原來元素的順序:

1. var healthFoods = new List<string> { "fruits", "vegetables", "grains", "proteins" }; 2. var myFoods = new List<string> { "grains", "proteins", "M&Ms", "soda" }; 3. // 返回序列: fruits, vegetables, grains, proteins, grains, proteins, M&Ms, soda 4. var healthyFirst = healthFoods.Concat(myFoods); 5. // 返回序列: grains, proteins, M&Ms, soda, fruits, vegetables, grains, proteins 6. var mineFirst = myFoods.Concat(healthFoods);

  Union() – 無重複項的串聯序列

  該方法用於結合兩個沒有重複項的集合,也非常適用於任何兩個序列。 它將第二個序列結合到第一個序列裏,當第二個序列中出現與第一個序列重複的項時,它只保留第一序列的項目。

  是否是重複的項目取決於IEqualityComparer <T> ,如果你沒有提供個性化的定義,則使用該類型的默認函數。 請注意,如果 T 是一個自定義的類型,這意味着你同時需要一個有效的Equals() 和 GetHashCode()的定義。

1. // 返回序列: fruits, vegetables, grains, proteins, M&Ms, soda 2. var healthyFirst = healthFoods.Union(myFoods); 3. // 返回序列: grains, proteins, M&Ms, soda, fruits, vegetables 4. var mineFirst = myFoods.Union(healthFoods);

  Zip() – 簡單一對一的聯接

  該方法針對兩個不同類執行一個最簡單的聯接。 比如給定兩個序列,它僅僅將他們的第一個項合併,而後將他們第二個項合併,…,一旦到達較短序列的最後一項,它就會立即停止。

  比方說,比如,我們有下面的類定義:

1. public class Employee 2. { 3. public int Id { get; set; } 4. public string Name { get; set; } 5. public double Salary { get; set; } 6. } 7. public class Seat 8. { 9. public int Id { get; set; } 10. public double Cost { get; set; } 11. }

  然後,我們確定了以下順序:

1. var employees = new List<Employee> 2. { 3. new Employee { Id = 13, Name = "John Doe", Salary = 13482.50 }, 4. new Employee { Id = 42, Name = "Sue Smith", Salary = 98234.13 }, 5. new Employee { Id = 99, Name = "Jane Doe", Salary = 32421.12 } 6. }; 7. var seats = new List<Seat> 8. { 9. new Seat { Id = 1, Cost = 42 }, 10. new Seat { Id = 2, Cost = 42 }, 11. new Seat { Id = 3, Cost = 100 }, 12. new Seat { Id = 4, Cost = 100 }, 13. new Seat { Id = 5, Cost = 125 }, 14. new Seat { Id = 6, Cost = 125 }, 15. };

  我們可以聯接它們,給每個僱員提供一個座位: 

1. var seatingAssignments = employees.Zip(seats, (e, s) => new 2. { EmployeeId = e.Id, SeatId = s.Id }); 3. foreach (var seat in seatingAssignments) 4. { 5. Console.WriteLine("僱員: " + seat.EmployeeId + " 預約了座位 " + seat.SeatId); 6. 7. }

  我們可以得到:

  僱員: 13 預約了座位1

  僱員: 42 預約了座位2

  僱員: 99 預約了座位3

  Join() – 滿足條件的聯接

  “使用 join 子句可以將來自不同源序列並且在對象模型中沒有直接關係的元素相關聯。 唯一的要求是每個源中的元素需要共享某個可以進行比較以判斷是否相等的值。 例如,食品經銷商可能具有某種產品的供應商列表以及買主列表。 例如,可以使用 join 子句創建該產品同一指定地區供應商和買主的列表。

  join 子句接受兩個源序列作爲輸入。 每個序列中的元素都必須是可以與另一個序列中的相應屬性進行比較的屬性,或者包含一個這樣的屬性。 join 子句使用特殊的 equals 關鍵字比較指定的鍵是否相等。 join 子句執行的所有聯接都是同等聯接。 join 子句的輸出形式取決於所執行的聯接的具體類型。 ”

  是否相等取決於IEqualityComparer<T>,如果你使用自定義的類型,你需要提供 Equals() 和 GetHashCode() 或者提供一個自定義的 IEqualityComparer<T>. 但是你使用的.NET 中的類型,則一般不需要再另外實現這些函數。

  上例子,使用之前的Employee類,再加一個Badge類,然後我們再創建這一組序列:

1. public class Badge 2. { 3. public int EmployeeId { get; set; } 4. public int BadgeNumber { get; set; } 5. } 6. var employees = new List<Employee> 7. { 8. new Employee { Id = 13, Name = "John Doe", Salary = 13482.50 }, 9. new Employee { Id = 42, Name = "Sue Smith", Salary = 98234.13 }, 10. new Employee { Id = 99, Name = "Jane Doe", Salary = 32421.12 } 11. }; 12. var badges = new List<Badge> 13. { 14. new Badge { EmployeeId = 10, BadgeNumber = 1 }, 15. new Badge { EmployeeId = 13, BadgeNumber = 2 }, 16. new Badge { EmployeeId = 20, BadgeNumber = 3 }, 17. new Badge { EmployeeId = 25, BadgeNumber = 4 }, 18. new Badge { EmployeeId = 42, BadgeNumber = 5 }, 19. new Badge { EmployeeId = 10, BadgeNumber = 6 }, 20. new Badge { EmployeeId = 13, BadgeNumber = 7 }, 21. };

  這樣我們就可以使用Join 來對它們進行操作了:

1. var badgeAssignments = employees.Join(badges, e => e.Id, b => b.EmployeeId, 2. (e, b) => new { e.Name, b.BadgeNumber }); 3. foreach (var badge in badgeAssignments) 4. { 5. Console.WriteLine("Name: " + badge.Name + " has badge " + badge.BadgeNumber); 6. }

  返回的結果是:

  Name: John Doe has badge 2

  Name: John Doe has badge 7

  Name: Sue Smith has badge 5

  Join 對於1:1的關係是非常實用的,或者如果你不在乎返回一些重複的1:N的關係,你也可以是用Join.

  GroupJoin() – 適用於一對多的條件聯接

  那麼,如果你有1:N的關係,你希望這些結果分類組合在一起就可以用到 GroupJoin(),仍舊用上面的例子:

1. var badgeAssignments = employees.GroupJoin(badges, e => e.Id, b => b.EmployeeId, 2. (e, bList) => new { Name = e.Name, Badges = bList.ToList() }); 3. foreach (var assignment in badgeAssignments) 4. { 5. Console.WriteLine(assignment.Name + " has badges:"); 6. if (assignment.Badges.Count > 0) 7. { 8. foreach (var badge in assignment.Badges) 9. { 10. Console.WriteLine("\tBadge: " + badge.BadgeNumber); 11. } 12. } 13. else 14. { 15. Console.WriteLine("\tNo badges."); 16. } 17. }

  結果如下:

1. John Doe has badges: 2. Badge: 2 3. Badge: 7 4. Sue Smith has badges: 5. Badge: 5 6. Jane Doe has badges: 7. No badges.

  如果你想進步一強化對Join 和 GroupJoin 區別的瞭解,可以再一次看看上面兩個例子輸入的結果。

發佈了47 篇原創文章 · 獲贊 3 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章