从外部方法调用 ruby 循环上的下一个
Posted
技术标签:
【中文标题】从外部方法调用 ruby 循环上的下一个【英文标题】:call next on ruby loop from external method 【发布时间】:2013-07-09 10:59:13 【问题描述】:在 Ruby 中,很容易告诉循环转到下一项
(1..10).each do |a|
next if a.even?
puts a
end
结果 =>
1
3
5
7
9
但是如果我需要从循环外部调用 next 怎么办(例如:方法)
def my_complex_method(item)
next if item.even? # this will obviously fail
end
(1..10).each do |a|
my_complex_method(a)
puts a
end
我找到并有效的唯一解决方案是使用throw
和catch
就像在SO 问题How to break outer cycle in Ruby? 中一样
def my_complex_method(item)
throw(:skip) if item.even?
end
(1..10).each do |a|
catch(:skip) do
my_complex_method(a)
puts a
end
end
我的问题是:任何人有任何更漂亮的解决方案来做到这一点?或者是throw/catch
唯一的方法吗??
如果我不仅想调用 my_complex_method
作为该循环的一部分(=> 不要抛出 :skip),我还能以某种方式告诉我的方法它是从循环中调用的吗?
【问题讨论】:
你真的,真的在想这个。返回一个值并根据返回值有条件地调用next
。这是软件中难以置信常见的模式,几乎适用于我曾经使用过的所有语言。 throw
/catch
这里没有位置。
我同意这个例子很荒谬,但我有一个需要分离循环和方法的案例
【参考方案1】:
您的复杂方法可以返回一个布尔值,然后您可以像这样在循环中进行比较:
def my_complex_method(item)
true if item.even?
end
(1..10).each do |a|
next if my_complex_method(a)
puts a
end
一种简单的方法,但与 try catch 不同。
更新
由于item.even?
已经返回一个布尔值,你不需要true if item.even?
部分,你可以这样做:
def my_complex_method(item)
item.even?
end
【讨论】:
我会选择这个答案,因为它让我意识到我的真实代码中的my_complex_method
可以用不同的方式编写,因此可以实现(以及 Meagar 对我的问题的评论)。 .. 但如果有人需要使用我在问题中描述的功能,我会使用Pritis answer 而不是我的throw/catch
解决方案【参考方案2】:
Enumerator#next
和 Enumerator#peek
将是 goo 的不错选择:
def my_complex_method(e)
return if e.peek.even?
p e.peek
end
enum = (1..5).each
enum.size.times do |a|
my_complex_method(enum)
enum.next
end
输出
1
3
5
【讨论】:
【参考方案3】:如果您只需要根据my_complex_method
返回的值对部分值执行操作,则可以明智地使用枚举数:
(1..10).map |a| [a, my_complex_method(a)] .each do |a, success|
puts a if success
end
您可以定义方法接受块并根据那里的成功或失败在此块中采取一些行动:
(1..10).each 做 |a|
我的复杂方法 |成功|接下来如果成功
结尾
由于作用域,您可以不使用 `catch`/`throw`,并根据处理状态调用 `next`。
【讨论】:
据我所知,第一种方法不起作用 -next
没有传递给 each
啊,你说得对——next
这里指的是my_complex_method
中定义的yield...以上是关于从外部方法调用 ruby 循环上的下一个的主要内容,如果未能解决你的问题,请参考以下文章
停止动态加载的 .SWF 循环,然后移动到主时间线上的下一帧