Pairs 関数

Python

>>> [(i, j) for i in range(3) for j in range(3)]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

のような各ペアを求める Pairs 関数を作成してみました。

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

public static class Iter {
    static IEnumerable<T[]> Product_1<T>(int p, T[] buf, List<List<T>> pools) {
        if (p == buf.Length) {
            yield return buf;
        }
        else {
            foreach (var e in pools[p]) {
                buf[p] = e;
                foreach (var ret in Product_1(p+1, buf, pools)) {
                    yield return ret;
                }
            }
        }
    }

    public static IEnumerable<T[]> Product<T>(IEnumerable<T> xs, int repeat = 1) {
        var pools = new List<List<T>>(Enumerable.Repeat(xs.ToList(), repeat));
        return Product_1(0, new T[pools.Count], pools);
    }

    public static IEnumerable<T[]> Product<T>(IEnumerable<T> xs, IEnumerable<T> ys, int repeat = 1) {
        var ls = new List<List<T>> { xs.ToList(), ys.ToList() };
        var pools = new List<List<T>>(Enumerable.Repeat(ls, repeat).SelectMany(e => e));
        return Product_1(0, new T[pools.Count], pools);
    }

    public static IEnumerable<U> Pairs<T, U>(IEnumerable<T> xs, IEnumerable<T> ys, Func<T, T, U> fn) {
        foreach (var e in Product(xs, ys)) {
            var cs = e.ToArray();
            yield return fn(cs[0], cs[1]);
        }
    }
}

class Program {
    static void Main() {
        var xs = new[] { 0, 1, 2 };
        var ys = Iter.Pairs(xs, xs, (a, b) => Tuple.Create(a, b));
        Console.WriteLine(string.Join(" ", ys));
        // => (0, 0) (0, 1) (0, 2) (1, 0) (1, 1) (1, 2) (2, 0) (2, 1) (2, 2)
    }
}

Product を経由せずに、foreach で 2 重ループを回すほうが簡単ですが、Product の応用を考えていて Pairs を作れることが分かったので作ってみました。

リンク