2016-08-09 4 views
4

私は2つの列挙子enum1enum2が遅延的に繰り返される必要があるとします(副作用があるため)。どのようにして第3の列挙子を構成しますかenum3ここでenum3.each{|x| x}となります。enum1 + enum2と等価ですか?2つの他の列挙子を使って遅延を繰り返すルビの列挙子を作るにはどうしたらいいですか?

私の実際の使用例では、2つのファイルにストリーミングしており、連結をストリーミングする必要があります。ここで

答えて

5

これは、ように見えますちょうど私がしたい方法で働く;

enums.lazy.flat_map{|enum| enum.lazy } 

ここにデモンストレーションがあります。これらの降伏方法を副作用で定義する。

def test_enum 
    return enum_for __method__ unless block_given? 
    puts 'hi' 
    yield 1 
    puts 'hi again' 
    yield 2 
end 

def test_enum2 
    return enum_for __method__ unless block_given? 
    puts :a 
    yield :a 
    puts :b 
    yield :b 
end 

concated_enum = [test_enum, test_enum2].lazy.flat_map{|en| en.lazy } 

次に、副作用が遅延していることを示す結果を次に呼び出します。

[5] pry(main)> concated_enum.next 
hi 
=> 1 
[6] pry(main)> concated_enum.next 
hi again 
=> 2 
+1

'flat_map'ソリューションに感謝します。 flat_mapの怠惰をすでに確認したにもかかわらず、これは私たちには発生せず、怠け者の追加として使用することができました! :) –

+0

このソリューションの欠点は、 'concated_enum.size'は常に' nil'を返すことです。 – skalee

+0

@skalee私はそれが怠惰なenumの欠点だと思う。あなたがそれらを反復するまで、あなたはどれくらいの大きさであるかを決して知ることはできません。それらのサイズは、あなたが反復するのにかかる時間の関数であるかもしれません。彼らは無限でもあります。 –

0

はでスロー怠惰な列挙といくつかのcode I wrote for fun awhile backです:

def cat(*args) 
    args = args.to_enum 

    Enumerator.new do |yielder| 
    enum = args.next.lazy 

    loop do 
     begin 
     yielder << enum.next 
     rescue StopIteration 
     enum = args.next.lazy 
     end 
    end 
    end 
end 

あなたはこのようにそれを使用します。

enum1 = [1,2,3] 
enum2 = [4,5,6] 
enum3 = cat(enum1, enum2) 

enum3.each do |n| 
    puts n 
end 
# => 1 
# 2 
# 3 
# 4 
# 5 
# 6 

...あるいは単に:

cat([1,2,3],[4,5,6]).each {|n| puts n } 
関連する問題