You can do this quite neatly with a generator. The generator will track which key is currently in use, which you cannot do with the traditional LINQ query without introducing external variables. You just need to decide when the key should change as you progress through the collection. Once you get a key to use for each item, just group it with that key.
public static class Extensions { public static IEnumerable<IGrouping<TKey, TResult>> ConsecutiveGroupBy<TSource, TKey, TResult>( this IEnumerable<TSource> source, Func<TSource, bool> takeNextKey, Func<TSource, TKey> keySelector, Func<TSource, TResult> resultSelector) { return from kvp in AssignKeys(source, takeNextKey, keySelector) group resultSelector(kvp.Value) by kvp.Key; } private static IEnumerable<KeyValuePair<TKey, TSource>> AssignKeys<TSource, TKey>( IEnumerable<TSource> source, Func<TSource, bool> takeNextKey, Func<TSource, TKey> keySelector) { var key = default(TKey); foreach (var item in source) { if (takeNextKey(item)) key = keySelector(item); yield return new KeyValuePair<TKey, TSource>(key, item); } } }
Then, to use it:
var lines = new List<string> { "Group Hear It:", " item: The Smiths", " item: Fernando Sor", "Group See It:", " item: Longmire", " item: Ricky Gervais Show", " item: In Bruges", }; var query = lines.ConsecutiveGroupBy( line => line.StartsWith("Group"), line => line, line => line);
Jeff mercado
source share