如何创建一个通过其他两个枚举器进行延迟迭代的ruby枚举器?

时间:2016-08-09 20:05:03

标签: ruby enumerator lazy-sequences

假设我有两个枚举器enum1enum2必须延迟迭代(因为它们有副作用)。如何构建第三个枚举器enum3,其中enum3.each{|x| x} 懒惰返回等效的enum1 + enum2

在我的真实世界用例中,我在两个文件中流式传输,需要流式传输连接。

3 个答案:

答案 0 :(得分:8)

这似乎与我想要的一样;

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 }

然后在结果上调用next,表明副作用懒散地发生;

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

答案 1 :(得分:1)

这里有一些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 }

答案 2 :(得分:0)

从Ruby 2.6开始,您可以使用Enumerable#chain / Enumerator::Chain

a = [1, 2, 3].lazy
b = [4, 5, 6].lazy

a.chain(b).to_a
# => [1, 2, 3, 4, 5, 6]

Enumerator::Chain.new(a, b).to_a
# => [1, 2, 3, 4, 5, 6]