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);
}
}
}
/// <summary>
/// シーケンス中の値と、階差(前の要素との差分)のペア。
/// </summary>
public class ValueDifferencePair
{
public ValueDifferencePair(int value, int difference)
{
this.value = value;
this.difference = difference;
}
private readonly int value;
/// <summary>
/// 値。
/// </summary>
public int Value
{
get { return value; }
}
private readonly int difference;
/// <summary>
/// 前の要素との差分。
/// </summary>
public int Difference
{
get { return difference; }
}
}
public static partial class IntegerSequence
{
/// <summary>
/// 隣り合ってる同じ値を1つにまとめてしまう。
/// </summary>
/// <typeparam name="T">要素の型</typeparam>
/// <param name="seq">元シーケンス。</param>
/// <returns>隣り合った重複を削除したシーケンス。</returns>
public static IEnumerable<T> DistinctAdjacently<T>(this IEnumerable<T> seq)
where T : struct
{
T? prev = null;
foreach (var x in seq)
{
if (prev == null || !prev.Equals(x))
{
yield return x;
}
prev = x;
}
}
/// <summary>
/// 特定の条件を満たすところでシーケンスを分割する。
/// (条件を満たした箇所がサブ シーケンスの先頭になる。)
///
/// 例えば、{ 1, 1, 0, 1, 1, 0 } というシーケンスを渡して、
/// 「要素が 0」という条件で分割すると、結果は
/// { { 1, 1 }, { 0, 1, 1 }, { 0 } }
/// となる。
/// </summary>
/// <typeparam name="T">要素の型</typeparam>
/// <param name="seq">元シーケンス。</param>
/// <param name="splitCondition">分割条件。</param>
/// <returns>分割したサブ シーケンス群。</returns>
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> seq, Predicate<T> splitCondition)
{
List<T> sub = null;
foreach (var x in seq)
{
if (splitCondition(x) && sub != null)
{
yield return sub;
sub = new List<T>();
}
if (sub == null)
{
sub = new List<T>();
}
sub.Add(x);
}
if (sub != null && sub.Count != 0)
{
yield return sub;
}
}
/// <summary>
/// シーケンスの階差を作る。
/// </summary>
/// <param name="seq">シーケンス。</param>
/// <returns>値/階差のペアのシーケンス。</returns>
public static IEnumerable<ValueDifferencePair> Differences(this IEnumerable<int> 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;
}
}
}
}