group
子句返回一个 IGrouping<TKey,TElement> 对象序列,这些对象包含零个或更多与该组的键值匹配的项。 例如,可以按照每个字符串中的第一个字母对字符串序列进行分组。 在这种情况下,第一个字母就是键,类型为 char,并且存储在每个 IGrouping<TKey,TElement> 对象的 Key
属性中。 编译器可推断键的类型。
可以用 group
子句结束查询表达式,如以下示例所示:
// Query variable is an IEnumerable<IGrouping<char, Student>> var studentQuery1 = from student in students group student by student.Last[0];
如果要对每个组执行附加查询操作,可使用上下文关键字 into 指定一个临时标识符。 使用 into
时,必须继续编写该查询,并最终使用一个select
语句或另一个 group
子句结束该查询,如以下代码摘录所示:
// Group students by the first letter of their last name // Query variable is an IEnumerable<IGrouping<char, Student>> var studentQuery2 = from student in students group student by student.Last[0] into g orderby g.Key select g;
枚举查询分组的结果
由于 group
查询产生的 IGrouping<TKey,TElement> 对象实质上是一个由列表组成的列表,因此必须使用嵌套的 foreach 循环来访问每一组中的各个项。 外部循环用于循环访问组键,内部循环用于循环访问组本身包含的每个项。 组可能具有键,但没有元素。 下面的 foreach
循环执行上述代码示例中的查询:
// Iterate group items with a nested foreach. This IGrouping encapsulates // a sequence of Student objects, and a Key of type char. // For convenience, var can also be used in the foreach statement. foreach (IGrouping<char, Student> studentGroup in studentQuery2) { Console.WriteLine(studentGroup.Key); // Explicit type for student could also be used here. foreach (var student in studentGroup) { Console.WriteLine(" {0}, {1}", student.Last, student.First); } }
按复合键分组
希望按照多个键对元素进行分组时,可使用复合键。 使用匿名类型或命名类型来存储键元素,创建复合键。 在下面的示例中,假定已经使用名为 surname
和 city
的两个成员声明了类 Person
。 group
子句会为每组姓氏和城市相同的人员创建一个单独的组。
group person by new {name = person.surname, city = person.city};
如果必须将查询变量传递给其他方法,请使用命名类型。 使用键的自动实现的属性创建一个特殊类,然后替代 Equals 和 GetHashCode 方法。 还可以使用结构,在此情况下,并不严格要求替代这些方法。 有关详细信息,请参阅如何:使用自动实现的属性实现轻量类和如何:查询目录树中的重复文件 (LINQ)。 后一个主题包含的代码示例演示了如何将复合键与命名类型结合使用。
示例
此示例演示在创建组之后,如何使用通过 into
实现的延续对这些组执行附加逻辑。 有关详细信息,请参阅 into。 下面的示例查询每个组,仅选择键值为元音的元素。
class GroupClauseExample2 { static void Main() { // Create the data source. string[] words2 = { "blueberry", "chimpanzee", "abacus", "banana", "apple", "cheese", "elephant", "umbrella", "anteater" }; // Create the query. var wordGroups2 = from w in words2 group w by w[0] into grps where (grps.Key == 'a' || grps.Key == 'e' || grps.Key == 'i' || grps.Key == 'o' || grps.Key == 'u') select grps; // Execute the query. foreach (var wordGroup in wordGroups2) { Console.WriteLine("Groups that start with a vowel: {0}", wordGroup.Key); foreach (var word in wordGroup) { Console.WriteLine(" {0}", word); } } // Keep the console window open in debug mode Console.WriteLine("Press any key to exit."); Console.ReadKey(); } } /* Output: Groups that start with a vowel: a abacus apple anteater Groups that start with a vowel: e elephant Groups that start with a vowel: u umbrella */