我們已經(jīng)在上一節(jié)中看到了Join運算符。GroupJoin運算符執(zhí)行與Join運算符相同的任務(wù),不同之處在于GroupJoin根據(jù)指定的組鍵在組中返回結(jié)果。GroupJoin運算符基于鍵聯(lián)接兩個序列,并通過匹配鍵將結(jié)果分組,然后返回分組的結(jié)果和鍵的集合。
GroupJoin需要與Join相同的參數(shù)。GroupJoin具有以下兩種重載方法:
GroupJoin重載方法:
public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector); public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer);
正如您在第一個重載中看到的,方法接受五個輸入?yún)?shù)(除了第一個“this”參數(shù)):1)outer 2)inner 3)outerKeySelector 4)inner keyselector 5)resultSelector。請注意,resultSelector是Func委托類型,它的第二個輸入?yún)?shù)是內(nèi)部序列的IEnumerable類型。
現(xiàn)在,讓我們使用以下Student和Standard類來了解GroupJoin,其中Student類包括與Standard類的StandardID匹配的StandardID。
public class Student{
public int StudentID { get; set; }
public string StudentName { get; set; }
public int StandardID { get; set; }
}
public class Standard{
public int StandardID { get; set; }
public string StandardName { get; set; }
}考慮下面的GroupJoin查詢示例。
示例:方法語法C#中的GroupJoin
IList<Student> studentList = new List<Student>() {
new Student() { StudentID = 1, StudentName = "John", StandardID =1 },
new Student() { StudentID = 2, StudentName = "Moin", StandardID =1 },
new Student() { StudentID = 3, StudentName = "Bill", StandardID =2 },
new Student() { StudentID = 4, StudentName = "Ram", StandardID =2 },
new Student() { StudentID = 5, StudentName = "Ron" }
};
IList<Standard> standardList = new List<Standard>() {
new Standard(){ StandardID = 1, StandardName="Standard 1"},
new Standard(){ StandardID = 2, StandardName="Standard 2"},
new Standard(){ StandardID = 3, StandardName="Standard 3"}
};
var groupJoin = standardList.GroupJoin(studentList, //內(nèi)部序列
std => std.StandardID, //outerKeySelector
s => s.StandardID, //innerKeySelector
(std, studentsGroup) => new // resultSelector
{
Students = studentsGroup,
StandarFulldName = std.StandardName
});
foreach (var item in groupJoin)
{
Console.WriteLine(item.StandarFulldName );
foreach(var stud in item.Students)
Console.WriteLine(stud.StudentName);
}Standard 1: John, Moin, Standard 2: Bill, Ram, Standard 3:
在上面的GroupJoin查詢示例中,standardList是外部序列,因為查詢是從外部序列開始的。GroupJoin方法中的第一個參數(shù)是指定內(nèi)部序列,在上面的示例中為studentList。該方法的第二和第三個參數(shù)GroupJoin()是指定一個字段,該字段的值應(yīng)使用lambda表達式進行匹配,以便在結(jié)果中包含element。外部序列的鍵選擇器standard => standard.StandardID指示standardList中每個元素的StandardID字段應(yīng)與內(nèi)部序列studentList的鍵匹配student => student.StandardID。如果兩個鍵字段的值都匹配,則將該元素包括到分組集合studentsGroup中,其中鍵為StandardID。
Join方法中的最后一個參數(shù)是用于表達結(jié)果的表達式。在上面的示例中,結(jié)果選擇器包括分組的集合studentGroup和StandardName。
下圖說明了將內(nèi)部序列分組到studentsGroup集合中以匹配StandardID鍵,并且可以使用分組的集合來表示結(jié)果。

結(jié)果集將包含具有Students和StandardFullName屬性的匿名對象。學(xué)生屬性將是其StandardID與Standard.StandardID匹配的Student的集合。

您可以使用“ foreach”循環(huán)訪問結(jié)果。每個元素將具有StandardFullName&Students屬性,其中Student將是一個集合。
foreach (var item in groupJoinResult)
{
Console.WriteLine(item.StandarFulldName );
foreach(var stud in item.Students)
Console.WriteLine(stud.StudentName);
}以下是VB.Net中的GroupJoin示例:
示例:方法VB.Net中的GroupJoin
Dim groupJoin = standardList.GroupJoin( ' outer sequence
studentList, ' inner sequence
Function(s) s.StandardID, ' outerKeySelector
Function(stud) stud.StandardID, ' innerKeySelector
Function(s, studentGroup) New With { ' result selector
.students = studentGroup,
.standardName = s.StandardName
})
For Each item In groupJoin
Console.WriteLine(item.standardName)
For Each std In item.students
Console.WriteLine( std.StudentName)
Next
NextStandard 1: John, Moin, Standard 2: Bill, Ram, Standard 3:
查詢語法中的GroupJoin運算符與方法語法稍有不同。它需要一個外部序列,內(nèi)部序列,鍵選擇器和結(jié)果選擇器?!?on”關(guān)鍵字用于鍵選擇器,其中“等于”運算符的左側(cè)是outerKeySelector,而“等于”運算符的右側(cè)是innerKeySelector。使用into關(guān)鍵字創(chuàng)建分組的集合。
from ... in outerSequence join ... in innerSequence on outerKey equals innerKey into groupedCollection select ...
下面的示例演示了查詢語法中的GroupJoin。
IList<Student> studentList = new List<Student>() {
new Student() { StudentID = 1, StudentName = "John", Age = 13, StandardID =1 },
new Student() { StudentID = 2, StudentName = "Moin", Age = 21, StandardID =1 },
new Student() { StudentID = 3, StudentName = "Bill", Age = 18, StandardID =2 },
new Student() { StudentID = 4, StudentName = "Ram" , Age = 20, StandardID =2 },
new Student() { StudentID = 5, StudentName = "Ron" , Age = 15 }
};
IList<Standard> standardList = new List<Standard>() {
new Standard(){ StandardID = 1, StandardName="Standard 1"},
new Standard(){ StandardID = 2, StandardName="Standard 2"},
new Standard(){ StandardID = 3, StandardName="Standard 3"}
};
var groupJoin = from std in standardList
join s in studentList
on std.StandardID equals s.StandardID
into studentGroup
select new {
Students = studentGroup ,
StandardName = std.StandardName
};
foreach (var item in groupJoin)
{
Console.WriteLine(item.StandarFulldName );
foreach(var stud in item.Students)
Console.WriteLine(stud.StudentName);
}Dim groupJoin = From s In standardList Group Join stud In studentList On stud.StandardID Equals s.StandardID Into Group _ Select _ StudentsGroup = Group, StandardName = s.StandardName
Standard 1: John, Moin, Standard 2: Bill, Ram, Standard 3:
在VB.Net版,InTo關(guān)鍵字將創(chuàng)建一個具有相同標(biāo)準(zhǔn)的所有學(xué)生的組,并將其分配給group關(guān)鍵字。所以,在投影結(jié)果中使用Group。