比較関数を渡せる GroupBy メソッドを作る

比較関数を渡せる GroupBy メソッドを作ってみました。

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

class Program {
    static IEnumerable<T[]> GroupBy<T>(IEnumerable<T> xs, Func<T, T, bool> match) {
        var ls = new List<T>();
        foreach (var x in xs) {
            if (ls.Count == 0 || match(ls[ls.Count-1], x)) {
                ls.Add(x);
            }
            else {
                yield return ls.ToArray();
                ls.Clear();
                ls.Add(x);
            }
        }
        if (ls.Count > 0) {
            yield return ls.ToArray();
        }
    }

    static void Display<T>(IEnumerable<T[]> xxs) {
        var xs = xxs.Select(e => string.Format("[{0}]", string.Join(", ", e)));
        var s = string.Format("[{0}]", string.Join(", ", xs));
        Console.WriteLine(s);
    }

    static void Main() {
        Display(GroupBy(new[] { 1, 2, 1, 2, 5, 1 }, (a, b) => a < b));
        // => [[1, 2], [1, 2, 5], 1]

        Display(GroupBy(new[] { 1, 1, 1, 2, 2, 5 }, (a, b) => a == b));
        // => [[1, 1, 1], [2, 2], [5]

        Display(GroupBy(new[] { 1, 1, 1, 2, 2, 5 }, (a, b) => a != b));
        // => [[1], [1], [1, 2], [2, 5]]

        Display(GroupBy("Mississippi", (a, b) => a == b));
        // => [[M], [i], [s, s], [i], [s, s], [i], [p, p], [i]]
    }
}

実行結果です。

[[1, 2], [1, 2, 5], [1]]
[[1, 1, 1], [2, 2], [5]]
[[1], [1], [1, 2], [2, 5]]
[[M], [i], [s, s], [i], [s, s], [i], [p, p], [i]]

リンク