分组运算符的作用与SQL查询的GroupBy子句相同。分组运算符根据给定的键创建一组元素。该组包含在实现IGrouping <TKey,TSource>接口的特殊类型的集合中,其中TKey是键值,在其上已形成该组,TSource是与该分组键值匹配的元素的集合。
分组运算符 | 描述 |
---|---|
GroupBy | GroupBy操作符根据某个键值返回元素组。每个组由 IGrouping<TKey,TElement>对象表示。 |
ToLookup | ToLookup 与 GroupBy 相同; 唯一的区别是 GroupBy 的执行被延迟,而 ToLookup 的执行是立即的。 |
GroupBy运算符基于某个键值从给定集合返回一组元素。每个组由IGrouping <TKey,TElement>对象表示。另外,GroupBy方法有8个重载方法,因此您可以根据需要在方法语法中使用适当的扩展方法。
LINQ查询可以以GroupBy或Select子句结尾。
GroupBy运算符的结果是组的集合。例如,GroupBy从Student集合返回IEnumerable <IGrouping <TKey,Student >>:
下面的示例创建一组年龄相同的学生。年龄相同的学生将在同一集合中,每个分组的集合将具有一个密钥和内部集合,其中密钥将是年龄,内部集合将包括年龄与密钥匹配的学生。
IList<Student> studentList = new List<Student>() { new Student() { StudentID = 1, StudentName = "John", Age = 18 } , new Student() { StudentID = 2, StudentName = "Steve", Age = 21 } , new Student() { StudentID = 3, StudentName = "Bill", Age = 18 } , new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 } , new Student() { StudentID = 5, StudentName = "Abram" , Age = 21 } }; var groupedResult = from s in studentList group s by s.Age; //遍历每组 foreach (var ageGroup in groupedResult) { Console.WriteLine("Age Group: {0}", ageGroup .Key); //每组都有一个钥匙 foreach(Student s in ageGroup) // 每组都有内部收藏 Console.WriteLine("Student Name: {0}", s.StudentName); }
AgeGroup: 18 StudentName: John StudentName: Bill AgeGroup: 21 StudentName: Steve StudentName: Abram AgeGroup: 20 StudentName: Ram
如上例所示,您可以使用“ foreach”循环对组进行迭代,其中每个组都包含一个键和内部集合。下图显示了调试视图中的结果。
如下所示,在VB.Net中,将“Into Group”与中的“Group By”子句一起使用。
Dim groupQuery = From s In studentList Group By s.Age Into Group For Each group In groupQuery Console.WriteLine("Age Group: {0}", group.Age) // 每个组都有关键属性名称 For Each student In group.Group // 每组都有内部收藏 Console.WriteLine("Student Name: {0}", student.StudentName) Next Next
请注意,每个组都有一个执行该组的属性名称。在上面的示例中,我们使用Age来组成一个组,因此每个组将使用“ Age”属性名称而不是“ Key”作为属性名称。
AgeGroup: 18 StudentName: John StudentName: Bill AgeGroup: 21 StudentName: Steve StudentName: Abram AgeGroup: 20 StudentName: Ram
GroupBy()扩展方法工作在方法的语法一样。在GroupBy扩展方法中为键选择器字段名称指定lambda表达式。
IList<Student> studentList = new List<Student>() { new Student() { StudentID = 1, StudentName = "John", Age = 18 } , new Student() { StudentID = 2, StudentName = "Steve", Age = 21 } , new Student() { StudentID = 3, StudentName = "Bill", Age = 18 } , new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 } , new Student() { StudentID = 5, StudentName = "Abram" , Age = 21 } }; var groupedResult = studentList.GroupBy(s => s.Age); foreach (var ageGroup in groupedResult) { Console.WriteLine("Age Group: {0}", ageGroup.Key); //每组都有一个钥匙 foreach(Student s in ageGroup) //每个组都有一个内部集合 Console.WriteLine("Student Name: {0}", s.StudentName); }
Dim groupQuery = studentList.GroupBy(Function(s) s.Age) For Each ageGroup In groupQuery Console.WriteLine("Age Group: {0}", ageGroup.Key) //每组都有一个钥匙 For Each student In ageGroup.AsEnumerable() //每个组都有一个内部集合 Console.WriteLine("Student Name: {0}", student.StudentName) Next Next
AgeGroup: 18 StudentName: John StudentName: Bill AgeGroup: 21 StudentName: Steve StudentName: Abram AgeGroup: 20 StudentName: Ram
ToLookup与GroupBy相同;唯一的区别是GroupBy执行被推迟,而ToLookup执行是立即执行。另外,ToLookup仅适用于方法语法。查询语法不支持 ToLookup。
IList<Student> studentList = new List<Student>() { new Student() { StudentID = 1, StudentName = "John", Age = 18 } , new Student() { StudentID = 2, StudentName = "Steve", Age = 21 } , new Student() { StudentID = 3, StudentName = "Bill", Age = 18 } , new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 } , new Student() { StudentID = 5, StudentName = "Abram" , Age = 21 } }; var lookupResult = studentList.ToLookup(s => s.age); foreach (var group in lookupResult) { Console.WriteLine("Age Group: {0}", group.Key); //每组都有一个键 foreach(Student s in group) //每个组都有一个内部集合 Console.WriteLine("Student Name: {0}", s.StudentName); }
Dim loopupResult = studentList.ToLookup(Function(s) s.Age)
GroupBy&ToLookup返回一个具有键和基于键字段值的内部集合的集合。
GroupBy 延迟执行,而 ToLookup 立即执行。
LINQ查询语法可以以GroupBy或Select子句结尾。