連続する数値でグループ分けする

昇順に並んだ数値を、連続する数値ごとにグループ分けするプログラムです。

using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    static void Main() {
        int[] xs = { 1, 2, 3, 6, 9, 10, 13, 14, 15, 16, 99, 100 };

        var g = xs.Select((x, index) => new { x, index })
                  .GroupBy(e => e.x - e.index, e => e.x);
        foreach (var a in g) {
            Console.WriteLine(string.Join(", ", a));
        }
    }
}

実行結果です。

1, 2, 3
6
9, 10
13, 14, 15, 16
99, 100

仕組み

Select メソッドに 2 つの引数を受け取る関数を渡すと、2 番目の引数にはインデックスが渡されます。配列の要素からインデックスを引いた値をキーにしてグループ分けしています。連続する数値に対して、そのインデックスを引いた値が同一になることを利用しています。

以下は、配列の要素からインデックスを引くサンプルです。連続する値では同じ値になっているのが確認できます。

using System;
using System.Collections.Generic;
using System.Linq;

class Program {
    static void Main() {
        int[] xs = { 1, 2, 3, 6, 9, 10, 13, 14, 15, 16, 99, 100 };

        for (int i = 0; i < xs.Length; i++) {
            Console.WriteLine(xs[i] - i);
        }
    }
}

実行結果です。

1
1
1
3
5
5
7
7
7
7
89
89