7

我有一棵树,我正在尝试遍历。当我遍历它时,我保留了一堆枚举器,其中每个枚举器用于枚举树的孩子。

我希望能够复制这个枚举器堆栈并将其交给另一个对象,以便它可以从堆栈状态指示的位置开始遍历树。

当我尝试在 Enumerator 上调用 #dup 时,出现错误。是否可以复制枚举器?如果没有,我怎么能完成同样的事情?(我曾考虑将一堆整数作为索引,但我担心效率。

这是一些代码来显示我所看到的......

一旦第一个枚举器启动,就不能复制它。这就是我的情况。

a = [1,2,3].each
 => #<Enumerator: [1, 2, 3]:each> 
a.next
 => 1 
b = a.dup
TypeError: can't copy execution context
    from (irb):3:in `initialize_copy'
    from (irb):3:in `initialize_dup'
    from (irb):3:in `dup'
    from (irb):3
4

3 回答 3

1

实现您自己的枚举器类。

除了递增内部计数器之外,枚举器并没有太多魔力。

class MyArrayEnumerator
  def initialize(array)
    @ary,@n=array,0
  end
  def next
    raise StopIteration if @n == @ary.length
    a=@ary[@n];@n+=1;a
  end
end

class Array
  def my_each
    MyArrayEnumerator.new(self)
  end
end

a = [1,2,3].my_each # => #<MyArrayEnumerator:0x101c96588 @n=0, @array=[1, 2, 3]>
a.next # => 1
b = a.dup # => #<MyArrayEnumerator:0x101c95ae8 @n=1, @array=[1, 2, 3]>
a.next # => 2
b.next # => 2
于 2012-11-29T09:59:13.750 回答
1

Use clone instead:

e1 = [1,2,3].each
e1.dup # TypeError: can't copy execution context
e2 = e1.clone
e1.next #=> 1
e2.next #=> 1
于 2015-09-11T18:09:45.540 回答
0

在 Enumerator 的实例中保留一个“头”,并为后面的副本存储历史记录:

class Enum

  def initialize()
    @history = [] # history will be shared between instances
    @history_cursor = -1
    @head = Enumerator.new do |yielder|
      @yielder = yielder
      enumerate
    end
  end

  def next
    if @history_cursor < @history.count - 1
      @history[@history_cursor += 1]
    else
      new_item @head.next
    end
  end

  private

  def new_item item
    @history << item
    @history_cursor = @history.count - 1
    item
  end

  def enumerate
    13.times do |i|
      @yielder << i # yielder is shared between instances
    end
  end

end

用法:

enum1 = Enum.new
p enum1.next # 0
enum2 = enum1.clone
p enum2.next # 1
p enum1.next # 1
于 2021-10-19T15:47:24.090 回答