Ruby 可枚举重置?

标签 ruby

我无法准确理解 ruby​​ 枚举保留了多少状态。 我了解一些Python,所以我期望在我从可枚举中获取一个项目后,它消失了,并且当我获取另一个项目时,下一个项目将被返回。 奇怪的是,当我使用 next 时,确实会发生这种情况,但当我使用 takefirst 之类的东西时,不会发生这种情况。 这是一个例子:

a = [1,2,3].to_enum
# => #<Enumerator: [1, 2, 3]:each>
a.take(2)
# => [1, 2]
a.next
# => 1
a.next
# => 2
a.take(2)
# => [1, 2]
a.next
# => 3
a.next
# StopIteration: iteration reached an end
#        from (irb):58:in `next'
#        from (irb):58
#        from /usr/bin/irb:12:in `<main>'
a.take(2)
# => [1, 2]

似乎枚举在 next 调用之间保持状态,但在每次 take 调用之前重置?

最佳答案

这可能有点令人困惑,但值得注意的是,在 Ruby 中,有 Enumerator类和 Enumerable模块。

Enumerator 类包括 Enumerable(与大多数可枚举对象一样,例如 ArrayHash 等)。

next方法作为Enumerator的一部分提供,它确实有一个内部状态。您可以认为 Enumerator 与其他语言公开的 Iterator 概念非常接近。

实例化枚举器时,内部指针指向集合中的第一项。

2.1.5 :021 > a = [1,2,3].to_enum
 => #<Enumerator: [1, 2, 3]:each>
2.1.5 :022 > a.next
 => 1
2.1.5 :023 > a.next
 => 2

这并不是枚举器的唯一用途(否则它可能会被称为迭代器)。然而,这是已记录的功能之一。

An Enumerator can also be used as an external iterator. For example, #next returns the next value of the iterator or raises StopIteration if the Enumerator is at the end.

e = [1,2,3].each   # returns an enumerator object.
puts e.next   # => 1
puts e.next   # => 2
puts e.next   # => 3
puts e.next   # raises StopIteration

但正如我之前所说,Enumerator 类包含 Enumerable。这意味着 Enumerator 的每个实例都会公开旨在处理集合的 Enumerable 方法。在本例中,该集合是 Enumerator 所包装的集合。

take是一个通用的Enumerable方法。它旨在返回枚举中的前 N ​​个元素。需要注意的是,enum 指的是任何包含 Enumerable 的泛型类,而不是 Enumerator。因此,无论 Enumerator 实例中指针的位置如何,take(2) 都将返回集合的前两个元素。

让我向您展示一个实际的例子。我可以创建一个自定义类,并实现 Enumerable

class Example
  include Enumerable

  def initialize(array)
    @array = array
  end

  def each(*args, &block)
    @array.each(*args, &block)
  end
end

我可以混合Enumerable,只要我提供each的实现,我就可以免费获得所有其他方法,包括take .

e = Example.new([1, 2, 3])
 => #<Example:0x007fa9529be760 @array=[1, 2, 3]>
e.take(2)
 => [1, 2]

正如预期的那样,take 返回前 2 个元素。 take 忽略我的实现中的任何其他内容,就像在 Enumerable 中一样,包括状态或指针。

关于Ruby 可枚举重置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28438888/

相关文章:

ruby - 如果需要,如何自动安装 Ruby gem?

ruby - SOAP + SSL + Ruby Savon - HTTPClient::ConnectTimeoutError:执行已过期

ruby-on-rails - Rails 备份 : Generating Backup Model not running with Dokku

ruby - 在 collection_select rails 中选择多个选项

ruby - TestFirst.org Learn Ruby rake 和弃用警告 :should and :expect syntax

ruby-on-rails - 使用 Active Record exists 有什么区别?与 find_by 相比?

ruby - 如何执行 Dir.glob 但排除目录?

ruby - 计算句子 Ruby 的数量

Ruby 与 Go/sha256 hmac base64 编码字符串不匹配