循环遍历Ruby中的其余Enumerator

时间:2018-04-28 09:46:03

标签: ruby for-loop iterator enumerator

我在某个序列的中间有一个枚举器:

enum = (1..9).each
first = enum.next
second = enum.next

现在我想循环完成序列的其余部分(3..9个数字)。但是看似明显的解决方案(例如在python中工作),从序列的开头而不是第三个项重新开始:

for item in enum
    puts item
end
# prints 1..9 instead of 3..9

我找到的工作解决方案看起来很难看:

begin
    while item=enum.next
        puts item
    end
rescue StopIteration
end

所以问题是:有没有更好的红宝石解决方案来做这件事?为什么Ruby中的for循环以这种方式运行?

2 个答案:

答案 0 :(得分:5)

要直接回答您的问题,您当前的代码是正确的,但过度设计。你只需要这样做:

enum = (1..9).each
first = enum.next
second = enum.next

loop { puts enum.next }

枚举到达终点时,循环将break; loop为您自动救出StopIteration。如果您在循环之后再次呼叫enum.next ,则只会重新提升,而这在此处不会发生。

然而正如@mudasobwa指出的那样,使用这样的枚举非常通常;更常见的是使用(1..9).each_with_index并通过其索引显式处理第一个收益率。

答案 1 :(得分:3)

在红宝石中,强烈建议您不要使用forwhileuntil,除非您完全了解自己的行为和原因。

当我需要在Enumerable的前两个元素上做一些特殊时,我很难想象真正的问题(这可能意味着一个架构问题),而不是这个:

enum.next
enum.next
loop do
  begin
    puts enum.next
  rescue StopIteration
    break 
  end
end
那里不需要

更新: rescue,请参阅@ TomLord的回答澄清。

你最好这样做:

enum.with_index do |element, idx|
  print "First " if idx == 0
  print "Second " if idx == 1
  puts element
end

Iterator的内部几乎从不应该被明确调用,使用高效和惯用的迭代,映射和减少。