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;
}
}
}
}