LINQ聯(lián)接序列的五種簡單方法
今天我們來看看5種使用Linq函數(shù)聯(lián)接序列的方法,這5種方法可以歸入下列兩類:
同類的聯(lián)接
Concat()
Union()
不同類的聯(lián)接
Zip()
Join()
GroupJoin()
Concat() – 串聯(lián)序列
最簡單的序列合并,concat僅僅是將第二個序列接在***個序列后面, 注意:返回的序列并沒有改變原來元素的順序:
- var healthFoods = new List<string> { "fruits", "vegetables", "grains", "proteins" };
- var myFoods = new List<string> { "grains", "proteins", "M&Ms", "soda" };
- // 返回序列: fruits, vegetables, grains, proteins, grains, proteins, M&Ms, soda
- var healthyFirst = healthFoods.Concat(myFoods);
- // 返回序列: grains, proteins, M&Ms, soda, fruits, vegetables, grains, proteins
- var mineFirst = myFoods.Concat(healthFoods);
Union() – 無重復項的串聯(lián)序列
該方法用于結(jié)合兩個沒有重復項的集合,也非常適用于任何兩個序列。 它將第二個序列結(jié)合到***個序列里,當?shù)诙€序列中出現(xiàn)與***個序列重復的項時,它只保留***序列的項目。
是否是重復的項目取決于IEqualityComparer <T> ,如果你沒有提供個性化的定義,則使用該類型的默認函數(shù)。 請注意,如果 T 是一個自定義的類型,這意味著你同時需要一個有效的Equals() 和 GetHashCode()的定義。
- // 返回序列: fruits, vegetables, grains, proteins, M&Ms, soda
- var healthyFirst = healthFoods.Union(myFoods);
- // 返回序列: grains, proteins, M&Ms, soda, fruits, vegetables
- var mineFirst = myFoods.Union(healthFoods);
Zip() – 簡單一對一的聯(lián)接
該方法針對兩個不同類執(zhí)行一個最簡單的聯(lián)接。 比如給定兩個序列,它僅僅將他們的***個項合并,而后將他們第二個項合并,…,一旦到達較短序列的***一項,它就會立即停止。
比方說,比如,我們有下面的類定義:
- public class Employee
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public double Salary { get; set; }
- }
- public class Seat
- {
- public int Id { get; set; }
- public double Cost { get; set; }
- }
然后,我們確定了以下順序:
- var employees = new List<Employee>
- {
- new Employee { Id = 13, Name = "John Doe", Salary = 13482.50 },
- new Employee { Id = 42, Name = "Sue Smith", Salary = 98234.13 },
- new Employee { Id = 99, Name = "Jane Doe", Salary = 32421.12 }
- };
- var seats = new List<Seat>
- {
- new Seat { Id = 1, Cost = 42 },
- new Seat { Id = 2, Cost = 42 },
- new Seat { Id = 3, Cost = 100 },
- new Seat { Id = 4, Cost = 100 },
- new Seat { Id = 5, Cost = 125 },
- new Seat { Id = 6, Cost = 125 },
- };
我們可以聯(lián)接它們,給每個雇員提供一個座位:
- var seatingAssignments = employees.Zip(seats, (e, s) => new
- { EmployeeId = e.Id, SeatId = s.Id });
- foreach (var seat in seatingAssignments)
- {
- Console.WriteLine("雇員: " + seat.EmployeeId + " 預約了座位 " + seat.SeatId);
- }
我們可以得到:
雇員: 13 預約了座位1
雇員: 42 預約了座位2
雇員: 99 預約了座位3
Join() – 滿足條件的聯(lián)接
“使用 join 子句可以將來自不同源序列并且在對象模型中沒有直接關(guān)系的元素相關(guān)聯(lián)。 唯一的要求是每個源中的元素需要共享某個可以進行比較以判斷是否相等的值。 例如,食品經(jīng)銷商可能具有某種產(chǎn)品的供應(yīng)商列表以及買主列表。 例如,可以使用 join 子句創(chuàng)建該產(chǎn)品同一指定地區(qū)供應(yīng)商和買主的列表。
join 子句接受兩個源序列作為輸入。 每個序列中的元素都必須是可以與另一個序列中的相應(yīng)屬性進行比較的屬性,或者包含一個這樣的屬性。 join 子句使用特殊的 equals 關(guān)鍵字比較指定的鍵是否相等。 join 子句執(zhí)行的所有聯(lián)接都是同等聯(lián)接。 join 子句的輸出形式取決于所執(zhí)行的聯(lián)接的具體類型。 ”
是否相等取決于IEqualityComparer<T>,如果你使用自定義的類型,你需要提供 Equals() 和 GetHashCode() 或者提供一個自定義的 IEqualityComparer<T>. 但是你使用的.NET 中的類型,則一般不需要再另外實現(xiàn)這些函數(shù)。
上例子,使用之前的Employee類,再加一個Badge類,然后我們再創(chuàng)建這一組序列:
- public class Badge
- {
- public int EmployeeId { get; set; }
- public int BadgeNumber { get; set; }
- }
- var employees = new List<Employee>
- {
- new Employee { Id = 13, Name = "John Doe", Salary = 13482.50 },
- new Employee { Id = 42, Name = "Sue Smith", Salary = 98234.13 },
- new Employee { Id = 99, Name = "Jane Doe", Salary = 32421.12 }
- };
- var badges = new List<Badge>
- {
- new Badge { EmployeeId = 10, BadgeNumber = 1 },
- new Badge { EmployeeId = 13, BadgeNumber = 2 },
- new Badge { EmployeeId = 20, BadgeNumber = 3 },
- new Badge { EmployeeId = 25, BadgeNumber = 4 },
- new Badge { EmployeeId = 42, BadgeNumber = 5 },
- new Badge { EmployeeId = 10, BadgeNumber = 6 },
- new Badge { EmployeeId = 13, BadgeNumber = 7 },
- };
這樣我們就可以使用Join 來對它們進行操作了:
- var badgeAssignments = employees.Join(badges, e => e.Id, b => b.EmployeeId,
- (e, b) => new { e.Name, b.BadgeNumber });
- foreach (var badge in badgeAssignments)
- {
- Console.WriteLine("Name: " + badge.Name + " has badge " + badge.BadgeNumber);
- }
返回的結(jié)果是:
Name: John Doe has badge 2
Name: John Doe has badge 7
Name: Sue Smith has badge 5
Join 對于1:1的關(guān)系是非常實用的,或者如果你不在乎返回一些重復的1:N的關(guān)系,你也可以是用Join.
GroupJoin() – 適用于一對多的條件聯(lián)接
那么,如果你有1:N的關(guān)系,你希望這些結(jié)果分類組合在一起就可以用到 GroupJoin(),仍舊用上面的例子:
- var badgeAssignments = employees.GroupJoin(badges, e => e.Id, b => b.EmployeeId,
- (e, bList) => new { Name = e.Name, Badges = bList.ToList() });
- foreach (var assignment in badgeAssignments)
- {
- Console.WriteLine(assignment.Name + " has badges:");
- if (assignment.Badges.Count > 0)
- {
- foreach (var badge in assignment.Badges)
- {
- Console.WriteLine("\tBadge: " + badge.BadgeNumber);
- }
- }
- else
- {
- Console.WriteLine("\tNo badges.");
- }
- }
結(jié)果如下:
- John Doe has badges:
- Badge: 2
- Badge: 7
- Sue Smith has badges:
- Badge: 5
- Jane Doe has badges:
- No badges.
如果你想進步一強化對Join 和 GroupJoin 區(qū)別的了解,可以再一次看看上面兩個例子輸入的結(jié)果。
原文鏈接:http://www.cnblogs.com/multiplesoftware/archive/2011/05/17/2048319.html
【編輯推薦】