从其块中访问Ruby枚举器对象

时间:2018-06-15 03:42:32

标签: ruby enumeration

我想从块中访问枚举器的大小,如下所示:

["cat", "dog", "mouse"].each_with_index { |e, i| puts "#{i + 1} of #{x.size}: #{e}" }

其中x是运行each_with_index的数组。

我尝试了tap方法,但是这并没有像我想象的那样工作。

例如,这段代码似乎没问题,我想:

["cat", "dog", "mouse"].tap { |a| a.each_with_index { |e, i| puts "#{i + 1} of #{a.size}: #{e}" }} # Works, but why do I need two blocks?

我希望只使用一个块,而不是两个块。像这样:

["cat", "dog", "mouse"].each_with_index.tap { |a, e, i| puts "#{i + 1} of #{a.size}" } # Does not work

2 个答案:

答案 0 :(得分:3)

那是因为在调用each_with_index时,您可以使用您给出的两个参数在块内工作 - 在这种情况下,是项目及其索引。

通常你可以单独存储数组,然后从块中引用它:

animals = ["cat", "dog", "mouse"]
animals.each_with_index { |e, i| puts "#{i + 1} of #{animals.size}: #{e}" }

并且它有效,有两行代码和一个块,但是你将无法在块中引用你的动物数组。

所以你尝试使用tap似乎是更准确的想法。由于tap会自动生成块,这就是你想要的,然后返回self,你就可以在你的块中执行操作,因为你不需要做任何其他事情。

["cat", "dog", "mouse"].tap do |a|
  a.each_with_index do |e, i|
    puts "#{i + 1} of #{a.size}: #{e}"
  end
end

但为此你需要两个块,一个用于访问自己(["cat", "dog", "mouse"]),然后在each_with_index上使用self

答案 1 :(得分:2)

Ruby没有这样的方法,但你可以自己构建它:(这是为了演示目的,你通常不应该改变核心类)

class Enumerator
  def with_enum
    each do |*values|
      yield values, self
    end
  end
end

["cat", "dog", "mouse"].each.with_index(1).with_enum do |(e, i), enum|
  puts "#{i} of #{enum.size}: #{e}"
end

请注意enum是对枚举数的引用,而不是对数组本身的引用。 Enumerator不会公开它所指的对象。