順番はどう変えてもいいから、とにかく『どの要素もいつかは出てくる(有限ステップ以内には出てくる)』ように列挙したリストを返す関数を作ってみてください。
無限オブ無限
何か設問に裏の意図がありそうな気配を感じますが、あっさり釣られます。無限リストの無限リスト限定ならわりとシンプル。
def iflatten(g) a = [] loop { a << g.next; a.each {|a| yield a.next } } end
でもこれは有限リストが混ざるとうまく動きません。有限リスト対応版はなんだか複雑。
def iflatten(g) a = [] begin a << g.next rescue g = nil a = a.select {|a| yield a.next rescue next; true } end until !g && a.empty? end
手抜きしてるので、例外は勝手に潰されます。以下テスト。
def succs(x) loop { yield x; x = x.succ } end def iseq_of_iseq to_enum(:succs, "a") {|j| to_enum(:succs, "1") {|i| j + i } } end puts to_enum(:iflatten, iseq_of_iseq).take(20).join(", ")
$ ./ruby ~/iseq.rb a1, a2, b1, a3, b2, c1, a4, b3, c2, d1, a5, b4, c3, d2, e1, a6, b5, c4, d3, e2
考えてみると、Enumerator って必ずメソッドを定義しないと作れないんだなぁ。面倒かも。