VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Objective-C编程 >
  • linq学习6 Group & Join

制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
 

  本篇介绍Linq的Group和Join操作,继续使用《Linq 学习(3) 语法结构》中介绍的数据源。

  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 };

  结束语

  到现在,Linq与SQL语言等价的操作基本介绍完,组合这些操作能实现复杂的查询。

 

 

  等效的扩展方法调用实现为:

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 }
// ...



相关教程