Another idea is to use a richer arsenal of LINQ operators.
First of all, let's connect the package MoreLinq (package manager console → Install-Package morelinq ).
To begin with, we need to find out for each of the elements whether it is necessary to finish the group on it. For this you need to consult with the previous item. This opportunity gives us the function Pairwise . Now, at the same time, we will “swallow” the first (or last) element, so we need to add it using the Prepend function.
For the time being we get:
src.Pairwise((prev, next) => new { val = next, sameGroup = next - prev == 1 }) .Prepend(new { val = src[0], sameGroup = true })
Now, we need to group the sequence into chunks depending on the value of the sameGroup . I did not find such functionality out of the box, but it is easy to implement it myself:
static class EnumerableExtensions { public static IEnumerable<IEnumerable<U>> SplitBy<T, U>( this IEnumerable<T> source, Func<T, bool> mayAppend, Func<T, U> selector) { var chunk = new List<U>(); foreach (var x in source) { if (!mayAppend(x)) { yield return chunk; chunk = new List<U>(); } chunk.Add(selector(x)); } if (chunk.Any()) yield return chunk; } }
Total:
static void Main(string[] args) { var src = new List<int> { 0, 1, 3, 5, 6, 7, 9 }; var result = src.Pairwise((prev, next) => new { val = next, sameGroup = next - prev == 1 }) .Prepend(new { val = src[0], sameGroup = true }) .SplitBy(vs => vs.sameGroup, vs => vs.val); foreach (var seq in result) Console.WriteLine(string.Join(" ", seq)); }
displays
0 1
3
5 6 7
9