Group
Group是进行分组操作,同SQL中的Group By类似。
原型如下:
public static IEnumerable < IGrouping < TKey, TSource >> GroupBy < TSource, TKey > ( this IEnumerable < TSource > source, Func < TSource, TKey > keySelector)
它有几个重载,返回类型有两种:IEnumerable<IGrouping<TKey, TSource>> 和 IEnumerable<TResult>。
返回类型为:IEnumerable<IGrouping<TKey, TSource>>示例:
返回按学号分组学生的成绩
var result = from score in DataSource.Scores group score by score.StudentID into scoreGroup select scoreGroup;
scoreGroup为IGrouping<TKey, TSource>类型,返回结果为IEnumerable<IGrouping<TKey, TSource>>,既集合的集合,因此输出时需用双重循环。
IGrouping<TKey, TElement>接口定义为:
public interface IGrouping < TKey, TElement > : IEnumerable < TElement > , IEnumerable { TKey Key { get ; } } 其中Key为分组依据的字段。
foreach ( var group in result) { // 输出分组依据的字段 Console.WriteLine( " \nStudent ID: " + group .Key); // 输出组内成员 foreach ( var score in group ) { Console.WriteLine(score); } } // result: // Student ID:1 // Student ID:1,Course ID:1,Score:78 // Student ID:1,Course ID:2,Score:60 // ... // Student ID:2 // Student ID:2,Course ID:1,Score:59 // ...
等效的扩展方法调用实现为:
var result = DataSource.Scores.GroupBy(score => score.StudentID);
返回类型为:IEnumerable<TResult>
对分组结果进行一些包装,如包装为匿名类型。
返回按学号分组学生的成绩
var result = from score in DataSource.Scores group score by score.StudentID into scoreGroup select new { StudentID = scoreGroup.Key, Group = scoreGroup };
匿名类型中Group为IGrouping<TKey, TSource>类型。
等效的扩展方法调用实现为:
var result = DataSource.Scores.GroupBy(score => score.StudentID, (key, group ) => new { StudentID = key, Group = group });
其他一些重载使用方法类似。
Join
连接操作。
public static IEnumerable < TResult > Join < TOuter, TInner, TKey, TResult > ( this IEnumerable < TOuter > outer, IEnumerable < TInner > inner, Func < TOuter, TKey > outerKeySelector, Func < TInner, TKey > innerKeySelector, Func < TOuter, TInner, TResult > resultSelector)
从Join方法原型可以看出其使用方法。
内连接
选择左右两侧集合都含有相对应的元素。
示例:
查询学生的姓名、学科、成绩。
var result = from score in DataSource.Scores join student in DataSource.Students on score.StudentID equals student.StudentID join course in DataSource.Courses on score.CourseID equals course.CourseID select new { StudentName = student.Name, CourseName = course.CourseName, ScoreValue = score.Value }; // result // { StudentName = Andy, CourseName = C Language, ScoreValue = 78 } // { StudentName = Andy, CourseName = Biophysics, ScoreValue = 60 } // ... // { StudentName = Bill, CourseName = C Language, ScoreValue = 59 } // { StudentName = Cindy, CourseName = Biophysics, ScoreValue = 60 } // ...
等效的扩展方法调用实现为:
var result = DataSource.Scores.Join( DataSource.Students, score => score.StudentID, student => student.StudentID, (score, student) => new { StudentName = student.StudentID, ScoreValue = score.Value, CourseID = score.CourseID }) .Join(DataSource.Courses, scostu => scostu.CourseID, course => course.CourseID, (scostu, course) => new { StudentName = scostu.StudentName, CourseName = course.CourseName, ScoreValue = scostu.ScoreValue });
左外连接当右侧的连接的右侧没有左侧对应的元素时,内连接会忽略左侧元素。要想保留左侧元素,可以使用做外连接。右侧被置为默认值,如:引用类型被置为空。
示例:
var result = from student in DataSource.Students2 join score in DataSource.Scores on student.StudentID equals score.StudentID into Scores from score in Scores.DefaultIfEmpty() select new { student = student, score = score == default (Score) ? 0 : score.Value }; // result: // { student = Student ID:5,Student Name:Erik, score = 78 } // { student = Student ID:6,Student Name:Frank, score = 0 } 等效的扩展方法调用实现为: var result = DataSource.Students2.GroupJoin( DataSource.Scores, student => student.StudentID, score => score.StudentID, (student, Scores) => new { student = student, Scores = Scores }) .SelectMany( group => group .Scores.DefaultIfEmpty(), ( group , score) => new { student = group .student, score = (score == null ) ? 0.0 : score.Value });
笛卡尔积集合中的元素交错连接。
示例:统计学生课程成绩时的模板。
var result = from student in DataSource.Students from course in DataSource.Courses select new { StudentName = student.Name, CourseName = course.CourseName, ScoreValue = ( double ? ) null }; // result: // { StudentName = Andy, CourseName = C Language, ScoreValue = } // { StudentName = Andy, CourseName = Biophysics, ScoreValue = } // ... // { StudentName = Bill, CourseName = C Language, ScoreValue = } // ... // { StudentName = Cindy, CourseName = Fundamentals of Compiling, ScoreValue = } // ... 等效的扩展方法调用实现为: var result = DataSource.Students.SelectMany( student => DataSource.Courses .Select( course => new { StudentName = student.Name, CourseName = course.CourseName, ScoreValue = ( double ? ) null }));
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) // result: // Andy // 1----78 // 2----60 // ... // Bill // 1----59 // ... // Cindy // 2----60 // ...
相当于组合了Group操作和Join操作。等效的操作如下:
var result = from item in ( from student in DataSource.Students join score in DataSource.Scores on student.StudentID equals score.StudentID select new { StudentName = student.Name, CourseID = score.CourseID, Value = score.Value }) group item by item.StudentName into Group select new { StudentName = Group.Key, Group = Group };