読者です 読者をやめる 読者になる 読者になる

Python の itertools.repeat を C# で作る

Pythonitertools.repeatC# で作ってみます。

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

class Repeat<T> : IEnumerable<T> {
    private const int INFINITY = -1; // 無限のときの _times の値

    private T _obj;
    private int _times;

    public Repeat(T obj) {
        _obj = obj;
        _times = INFINITY;
    }

    public Repeat(T obj, int times) {
        if (times < 0) throw new ArgumentOutOfRangeException();

        _obj = obj;
        _times = times;
    }

    public IEnumerator<T> GetEnumerator() {
        if (_times == -1) {
            while (true) {
                yield return _obj;
            }
        }
        else {
            for (int i = 0; i < _times; i++) {
                yield return _obj;
            }
        }
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return this.GetEnumerator();
    }
}

class Program {
    static void Main() {
        // MoveNext のサンプル
        var g = new Repeat<int>(10).GetEnumerator();
        for (int i = 0; i < 3; i++) {
            if (g.MoveNext()) {
                Console.WriteLine(g.Current);
            }
        }

        // foreach 文のサンプル
        foreach (var x in new Repeat<string>("hello", 3)) {
            Console.WriteLine(x);
        }

        // Linq の Take メソッドのサンプル
        Console.WriteLine(string.Join(" ", new Repeat<char>('c').Take(5)));

        // Python の map(pow, range(10), repeat(2))
        var q = Enumerable.Range(0, 10).Zip(new Repeat<int>(2), (a, b) => Math.Pow(a, b));
        Console.WriteLine(string.Join(" ", q));
    }

}

実行結果です。

10
10
10
hello
hello
hello
c c c c c
0 1 4 9 16 25 36 49 64 81