using System; using System.Linq; using System.Collections.Generic; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { int[] arraydada = { 1, 2, 2, 3, 10, 11, 100, 101, 102, 103 }; var groups = arraydada .DistinctAdjacently() .Differences() .Split(x => x.Difference != 1) .Select(x => new { First = x.First().Value, Count = x.Count() }); foreach (var g in groups) { Console.WriteLine("{0}を先頭に{1}個", g.First, g.Count); } } } /// /// シーケンス中の値と、階差(前の要素との差分)のペア。 /// public class ValueDifferencePair { public ValueDifferencePair(int value, int difference) { this.value = value; this.difference = difference; } private readonly int value; /// /// 値。 /// public int Value { get { return value; } } private readonly int difference; /// /// 前の要素との差分。 /// public int Difference { get { return difference; } } } public static partial class IntegerSequence { /// /// 隣り合ってる同じ値を1つにまとめてしまう。 /// /// 要素の型 /// 元シーケンス。 /// 隣り合った重複を削除したシーケンス。 public static IEnumerable DistinctAdjacently(this IEnumerable seq) where T : struct { T? prev = null; foreach (var x in seq) { if (prev == null || !prev.Equals(x)) { yield return x; } prev = x; } } /// /// 特定の条件を満たすところでシーケンスを分割する。 /// (条件を満たした箇所がサブ シーケンスの先頭になる。) /// /// 例えば、{ 1, 1, 0, 1, 1, 0 } というシーケンスを渡して、 /// 「要素が 0」という条件で分割すると、結果は /// { { 1, 1 }, { 0, 1, 1 }, { 0 } } /// となる。 /// /// 要素の型 /// 元シーケンス。 /// 分割条件。 /// 分割したサブ シーケンス群。 public static IEnumerable> Split(this IEnumerable seq, Predicate splitCondition) { List sub = null; foreach (var x in seq) { if (splitCondition(x) && sub != null) { yield return sub; sub = new List(); } if (sub == null) { sub = new List(); } sub.Add(x); } if (sub != null && sub.Count != 0) { yield return sub; } } /// /// シーケンスの階差を作る。 /// /// シーケンス。 /// 値/階差のペアのシーケンス。 public static IEnumerable Differences(this IEnumerable seq) { int? prev = null; foreach (var x in seq) { var diff = prev == null ? 0 : x - (int)prev; yield return new ValueDifferencePair(x, diff); prev = x; } } } }