我在理解 Ruby 中的枚举器时遇到了麻烦。

请纠正我如果我错了,o.enum_for(:arg) 方法应该将对象转换为 Enumerator,并且每次对对象 o 的迭代都应该调用 arg 方法?
令我困惑的是这行代码是如何工作的

[4, 1, 2, 0].enum_for(:count).each_with_index do |elem, index|
  elem == index
end

它应该计算有多少元素等于它们在数组中的位置,并且它可以工作。但是,我不明白实际发生了什么。 each_with_index 是否在每次迭代中都调用 count 方法?如果有人可以解释,那就太好了。

最佳答案

来自编程 Ruby:



因此,枚举器访问每个元素,如果块返回 true,则将计数加 1,在这种情况下,这意味着元素是否等于数组索引。

我还没有看到这种模式使用得太多(如果有的话)——我更倾向于:

[4, 1, 2, 0].each_with_index.select { |elem, index| elem == index }.count

编辑

让我们看一下您评论中的示例:
[4, 1, 2, 0].enum_for(:each_slice, 2).map do |a, b|
  a + b
end
each_slice(2) 一次获取数组 2 个元素,并为每个切片返回一个数组:
[4, 1, 2, 0].each_slice(2).map # => [[4,1], [2,0]]

对结果调用 map 可以让我们对每个子数组进行操作,并将其传递到一个块中:
[4, 1, 2, 0].enum_for(:each_slice, 2).map do |a,b|
  puts "#{a.inspect} #{b.inspect}"
end

结果是
4 1
2 0
ab 通过块参数“splatted”获得它们的值:
a, b = *[4, 1]
a # => 4
b # => 1

您也可以将数组切片作为参数:
[4, 1, 2, 0].enum_for(:each_slice, 2).map {|a| puts "#{a.inspect}"}

[4, 1]
[2, 0]

这可以让你做到这一点:
[4, 1, 2, 0].enum_for(:each_slice, 2).map {|a| a.inject(:+) } #=> [5,2]

或者,如果您有 ActiveSupport(即 Rails 应用程序),
[4, 1, 2, 0].enum_for(:each_slice, 2).map {|a| a.sum }

在我看来,这比原始示例要清楚得多。

关于ruby - Ruby 中的枚举器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13350207/

10-16 19:29