【问题标题】:cycle through the rest of Enumerator in Ruby在 Ruby 中循环遍历 Enumerator 的其余部分
【发布时间】:2018-10-09 01:12:36
【问题描述】:

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

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​​ish 解决方案来做这件事?为什么 Ruby 中的 for 循环会这样?

【问题讨论】:

    标签: ruby for-loop iterator enumerator


    【解决方案1】:

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

    enum = (1..9).each
    first = enum.next
    second = enum.next
    
    loop { puts enum.next }
    

    一旦枚举结束,循环将breakloop 会自动为你解救StopIteration。只有当你在循环之后调用enum.next再次,它才会重新引发,这里不会发生。

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

    【讨论】:

    • 哇,确实,rescue 是多余的,谢谢,从来不知道(这反过来意味着整个构造就像我在 5 年以上的经验中未能尝试它一样不红:)
    • @mudasobwa From the docs: "StopIteration - 引发以停止迭代,特别是由Enumerator#next。它被Kernel#loop 救出。" 但是是的,尽管有类似的经验,但我也必须仔细检查;在 ruby​​ 代码中看到 enum.next 非常罕见!
    • 不要低估enum.next!一个例子:n.public_send(enum.next, m),其中enum = [:+, :- ].cycle
    【解决方案2】:

    强烈建议在 ruby​​ 中不要使用 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 的内部几乎不应该被显式调用,而是使用高效且惯用的迭代、映射和归约。

    【讨论】:

    • with_index 在课堂上Enumerator,如果是这样,为什么enum.each.with_index 为什么不是enum.with_index
    • @Rajagopalan 触发迭代。 enum.with_index 返回一个枚举器。
    • p enum.each.with_index.class 也返回枚举数。
    • @Rajagopalan 啊,确实,你说得对,谢谢。更新了答案。
    • @Rajagopalan,大小写很重要:"enum.each.with_index.class" 返回类 Enumerator,而不是“枚举数”。此外,p 在开头打印"Enumerator",而不是返回Enumerator。准确!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    相关资源
    最近更新 更多