如何打破Ruby中的嵌套循环?

时间:2011-03-13 01:44:48

标签: ruby loops nested-loops

假设以下ruby代码:

bank.branches do |branch|
  branch.employees.each do |employee|
    NEXT BRANCH if employee.name = "John Doe"
  end
end

NEXT BRANCH当然是伪代码。有没有一种方法可以突破父循环,例如Perl中的方式(通过使用循环标签)?

提前感谢。

6 个答案:

答案 0 :(得分:84)

您可能正在寻找

Catch throw

bank.branches do |branch|
  catch :missingyear do  #:missingyear acts as a label
    branch.employees.each do |employee|
      (2000..2011).each do |year|
        throw :missingyear unless something  #break out of two loops
      end
    end
  end #You end up here if :missingyear is thrown
end

答案 1 :(得分:16)

没有他们的同意,没有内置的方法来打破包含块。你只需要做一些事情:

bank.branches do |branch|
  break unless branch.employees.each do |employee|
    break if employee.name == "John Doe"
  end
end

答案 2 :(得分:5)

while c1
 while c2
    # execute code
    do_break = true if need_to_break_out_of_parent_loop
 end
 break if do_break
end

答案 3 :(得分:4)

我的冲动是将嵌套的块移动到一个方法中,用return代替break

def find_branch_and_employee_by_name(bank,emp_name)
  bank.branches.each do |branch|
    branch.employees.each do |employee|
      return([branch,employee]) if employee.name == emp_name
    end
  end
  nil   # employee wasn't found
end

答案 4 :(得分:0)

修改 通过调用内部循环中的break(只会终止该循环),可以更简单地实现所需的效果:

bank.branches do |branch|
  branch.employees.each do |employee|
    break if employee.name = "John Doe"
  end
end

以下是 @steenslag 使用Ruby begin-rescue-end块编写的内容:

letters = [%w(a b c),%w(d e f),%w(g h i)]
# => [["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"]]

letters.each do |trine|
  begin
    trine.each do |letter|
      raise "Breaking out of inner cycle." if letter == "e"
      puts letter
    end
  rescue
    next
  end
end
# => abcdghi

所以你的例子是:

bank.branches do |branch|
  branch.employees.each do |employee|
    begin
      raise "Breaking out of inner cycle." if employee.name = "John Doe"
    rescue
      next
    end      
  end
end

答案 5 :(得分:0)

其他帖子引用了类似于创建“switch”变量的想法。请参阅下文,了解其工作原理的明确示例。请记住,第二个循环仍将一直运行,直到它到达employee数组的末尾,但在切换开关后不会执行任何代码。这不是执行此操作的最佳方式,因为如果您的员工阵列很大,则可能会花费不必要的时间。

def workforce
  bank.branches do |branch|
    switch = 0
    branch.employees.each do |employee|
      if switch == 1
       next
      end  
      if employee.name = "John Doe"
       switch = 1
      end
   end
 end

在翻转开关后,内部阵列将不再处于活动状态,并且父循环将在切换复位时移动到下一个分支。显然,更多的开关可以用于更复杂的情况。