【问题标题】:Skip iteration from yield block in ruby从ruby中的yield块跳过迭代
【发布时间】:2011-09-18 23:37:43
【问题描述】:

试图使用一个构思不当的框架,该框架从传入的块中收集结果列表,实际上是这样的:

def sigh(&block)
  r = (1..3).collect do |i|
     yield(i)
  end

  # do something with r
end

我希望我传入的块来过滤项目,但要跳过集合迭代,而不是像next那样将nil添加到结果中(因为框架不紧凑他们。)除了修补 gem 之外,还有什么简单的方法?即,

sigh {|i|  next unless i == 1 }  # results in [1,nil,nil] rather than just [1]

【问题讨论】:

  • 我感觉到你的未来有一个猴子补丁
  • 简单的“sigh { |i| next 除非 i == 1 }.compact”有什么问题?太冗长了?
  • 我需要将一个块传递给框架方法sigh,该方法过滤框架随后作用的结果。在结果中包含nil
  • 我现在看到了被问到的内容。我想不出办法。 break 将在此时从整个方法中逃脱。
  • @Wayne:除非它是开源 gem,否则最好的猴子补丁可能是拉取请求。

标签: ruby iteration block yield next


【解决方案1】:

坏消息是您必须修补 gem。让 gem 调用您的代码块不会赋予您的代码任何特殊权力来影响调用代码如何处理块的返回值。

好消息是,修补 gem 通常可以使用“猴子补丁”来完成,您的程序会重新打开 gem 的类或模块并进行更改。在这个虚构的示例中,我们将展示嵌套在模块中的类,因为许多 gem 都使用嵌套的类和模块:

require 'somegem'

# Monkey patch to cause Somegem's do_something_cool method
# to ignore the SomethingBadHappened exception

module SomeGem
  class SomeClass
    alias_method :orig_do_something_cool, :do_something_cool
    def do_something_cool
      orig_do_something_cool
    rescue SomethingBadHappened
    end
  end
end

【讨论】:

    【解决方案2】:

    没有办法按照你的要求去做。但是,如果您发布有关您正在使用的框架的更多详细信息,这里的某人可能会帮助您想出解决问题的不同方法。

    【讨论】:

      【解决方案3】:

      你需要修补,就像其他人说的那样。如果您想要满足某些条件的i 集合,最好的选择是将collect 替换为find_all,然后您可以使用:

      sigh { |i| i == 1 }   #=> [1]
      

      【讨论】:

        猜你喜欢
        • 2015-06-20
        • 1970-01-01
        • 2015-08-16
        • 2017-12-01
        • 2018-01-10
        • 1970-01-01
        • 2011-08-06
        • 2011-07-06
        • 1970-01-01
        相关资源
        最近更新 更多