How to break from nested loops in Ruby?

拜拜、爱过 提交于 2019-11-29 02:47:49

Catch and throw might be what you are looking for:

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

There's no built-in way to break out of containing blocks without their consent. You'll just have to do something like:

bank.branches do |branch|
  break unless branch.employees.each do |employee|
    break if employee.name == "John Doe"
  end
end
Anno2001
while c1
 while c2
    # execute code
    do_break = true if need_to_break_out_of_parent_loop
 end
 break if do_break
end

My impulse would be to move the nested blocks into a method, with a return in place of the 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

Edit: The desired effect, turns out, can be achieved much more simply by calling break inside the inner loop (will only terminate that loop):

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

Here is what @steenslag was getting at written with Ruby begin-rescue-end block:

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

So your example is:

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

Other posts have referenced an idea similar to creating a "switch" variable. See below for a clear example of how it works. Keep in mind the second loop will still be running until it reaches the end of the employee array, but will not execute any code after the switch is flipped. This is not the optimal way to do this as it can be unnecessarily time expensive if your employee array is large.

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

After the switch is flipped the inner array will no longer be active and the parent loop will move to the next branch with the switch reset. Obviously more switches can be used for more complex cases.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!