12

在 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

我找到并工作的唯一解决方案是在 SO 问题中使用throw& like如何打破 Ruby 中的外部循环?catch

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),我可以以某种方式告诉我的方法它是从循环中调用的吗?

4

3 回答 3

12

您的复杂方法可以返回一个布尔值,然后您在循环中进行比较,如下所示:

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
于 2013-07-09T11:13:39.627 回答
1

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
于 2013-07-09T11:17:06.923 回答
0

如果您只需要对某些值采取行动,则可以根据返回的值my_complex_method明智地使用枚举数:

(1..10).map { |a| [a, my_complex_method(a)] }.each do |a, success|
  puts a if success
end
您可以定义方法接受块并根据成功或失败在该块中采取一些行动: (1..10).each do |a| 我的复杂方法{ |成功| next if success } end 由于作用域,您可以不使用`catch`/`throw`,并根据处理状态调用`next`。
于 2013-07-09T11:20:08.463 回答