【发布时间】:2018-03-09 23:47:08
【问题描述】:
我刚刚遇到了一些有趣的 Enumerator 行为。 Enumerator 似乎对 Enumerable 中的位置存在某种依赖性 - 一旦您查看了 Enumerable 的结尾并且引发了 StopIteration,Enumerator 就不会注意到 Enumerable 的扩展。
两个例子演示:
a=[1, 2, 3]
e=a.each
=> #<Enumerator: [1, 2, 3]:each>
2.4.0 :027 > e.next
=> 1
2.4.0 :028 > a.insert(1, 4)
=> [1, 4, 2, 3]
2.4.0 :029 > e.next
=> 4
2.4.0 :031 > e.next
=> 2
好的,到目前为止,一切都很好。但是这个呢。让我们定义一个方法来在我们到达末尾时扩展数组:
def a_ext(a,enum)
enum.peek
rescue StopIteration
a << a[-1] + 1
end
现在让我们看看当我们使用它时会发生什么
2.4.0 :012 > a=[1, 2, 3]
=> [1, 2, 3]
2.4.0 :013 > e = a.each
=> #<Enumerator: [1, 2, 3]:each>
2.4.0 :016 > 3.times{e.next}
=> 3
我们已经到达数组的末尾 - 所以调用a_ext 来扩展数组
2.4.0 :018 > a_ext(a,e)
=> [1, 2, 3, 4]
2.4.0 :019 > e.peek
StopIteration: iteration reached an end
????!!
看起来一旦你点击了 StopIteration,Enumerator 就不会再次检查 Array(我猜一般来说是一个 Enumerable)是否已扩展。
这是预期的行为吗?一个错误?一个功能?
您为什么要这样做。好吧 - 使用哈希,您可以通过传递 Hash::new 一个块来设置默认值 - 您可以将一个块传递给 Array::new。但是Array::new 作为参数的块只有索引作为键,而不是数组和索引(如 Hash::new,其块产生哈希和键)。因此,这使得构建一个可以在枚举时扩展的数组变得非常丑陋和困难。
例如,想象一个约会日记,您想在其中枚举以查找第一个空闲日。这自然是一个 Array 而不是 Hash(因为它是有序的),但是在迭代它时很难扩展。
想法?
【问题讨论】:
-
恕我直言,您应该避免在迭代数组时更新数组以避免不一致。在您的示例中,您可以使用
find或find_index而不是使用枚举器。
标签: ruby enumerator