LINQ查询以识别系列中的片段

fah*_*ash 5 c# linq

假设我有以下数组(我的序列都按升序排序,并包含正整数)

var mySequence = new [] {1, 2, 3, 7, 8, 9, 15, 16, 17};
Run Code Online (Sandbox Code Playgroud)

我想写一个linq查询来选择被视为一个组的系列中的连续数字.所以,在上面的例子中我会得到{[1,2,3],[7,8,9],[15,16,17]}.

我可以编写一个foreach()序列,遍历每个元素,看看序列在哪里跳跃并在那里产生一个组.但有没有LINQ唯一的方法呢?我可能能够将我的foreach()代码移动到一个新的扩展方法,所以我的代码仍然看起来像LINQy,但我想知道System.Linq中是否有任何可用的东西.

编辑:我创建了自己的扩展(如下所示),但Me.Name在他的答案中提出了一些非常聪明的东西.

internal class Sequence
{
    public int Start { get; set; }
    public int End { get; set; }
}

internal static class EnumerableMixins
{
    public static IEnumerable<Sequence> GroupFragments(this IEnumerable<int> sequence)
    {
        if (sequence.Any())
        {
            var lastNumber = sequence.First();
            var firstNumber = lastNumber;

            foreach(var number in sequence.Skip(1))
            {
                if (Math.Abs(number - lastNumber) > 1)
                {
                    yield return new Sequence() { Start = firstNumber, End = lastNumber };

                    firstNumber = lastNumber = number;
                }
                else
                {
                    lastNumber = number;
                }
            }


            yield return new Sequence() { Start = firstNumber, End = lastNumber };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Me.*_*ame 10

找到这些岛屿的一个老技巧是减去索引和数值.结果将代表独特的群体.使用包含索引的select重载:

var mySequence = new [] {1, 2, 3, 7, 8, 9, 15, 16, 17};

var groups = mySequence
    .Select((val,ind) => new{val, group = val - ind})
    .GroupBy(v=>v.group, v=>v.val)
    .Select(v=> v.ToList()).ToList();
Run Code Online (Sandbox Code Playgroud)

(在这里使用ToList,但当然如果首选数组则可以使用ToArray)