Grouping in LINQ enables you to return
partitioned sets of data from a collection based on a given key value.
An example might be to group all Contact records by the State property. In LINQ this query can be simply written
var q = from c in contacts
group c by c.State;
Or if you prefer the extension method query syntax
var q = contacts.GroupBy(c => c.State);
The result from a LINQ grouping operation is an enumerable sequence of groups (themselves sequences), with each group having a distinct
key value. The key value is determined by the “key selection”
expression, which is an expression that equates the key value for each
element (c.State in the previous example). All source elements
that equate to an equal key value using the key selection expression
will be partitioned into the same group.
The GroupBy extension method operator has
many overloads; the simplest has just a single key selection argument.
The remaining overloads of this operator allow specific control of how
element equality is evaluated, the select projection to use for the
resulting groups, and what select projection is used for generating
each element in any resulting group.
The following GroupBy extension method signature shows all of the possible arguments:
public static IEnumerable<TResult>
GroupBy<TSource, TKey, TElement, TResult>
(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement>
elementSelector,
Func<TKey, IEnumerable<TElement>, TResult>
resultSelector,
IEqualityComparer<TKey> compare
)
Independent from how the GroupBy projects the results, the resulting sequence exposes groups that have a common Key property value. The members of these groupings can themselves be enumerated to obtain the individual group elements.
The key order by default is the order each key value
first appears in the source collection. If you want an alternative key
order, sort the source collection first using the normal ordering
operators.
|
1. Working with Groups
The return collection from a GroupBy or group x by y query is
IEnumerable<IGrouping<TKey, TElement>>
IGrouping interface inherits from IEnumerable<TElement> (making itself enumerable) and exposes a Key property that indicates the unique result that formed this grouping. This interface has the following form:
public interface IGrouping<TKey, TElmt> : IEnumerable<TElmt>
{
TKey Key { get; }
}
LINQ to Objects returns by default an internal concrete class implementation of IGrouping<Tkey, TElement>, called Grouping. It is exposed via the IGrouping
interface through the extension method signatures so that Microsoft can
develop this over time. The only property you should rely on is the Key property. Most methods on the underlying Grouping collection type throw a NotSupportedException and should be avoided.
Enumerating over the result of a GroupBy extension method or group x by y query expression yields one IGrouping<TKey, TElement> element per unique key. Each group instance has the mandatory Key property, and each group can be iterated to get the elements in that group.
The normal pattern for working with groups once they are generated is to use a nested foreach loop; the first enumerates the groups, and then an inner loop iterates the elements. The general pattern is
foreach (var group in q)
{
// Group specific code here
Console.WriteLine("Group key: {0}", group.Key);
foreach (var element in group)
{
// Element specific code here
Console.WriteLine(" - {0}", element);
}
}