How to break from nested loops in Ruby?

前端 未结 6 684
感情败类
感情败类 2020-12-15 15:00

assume the following ruby code:

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


        
相关标签:
6条回答
  • 2020-12-15 15:23

    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
    
    0 讨论(0)
  • 2020-12-15 15:29

    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
    
    0 讨论(0)
  • 2020-12-15 15:31

    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
    
    0 讨论(0)
  • 2020-12-15 15:39
    while c1
     while c2
        # execute code
        do_break = true if need_to_break_out_of_parent_loop
     end
     break if do_break
    end
    
    0 讨论(0)
  • 2020-12-15 15:41

    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.

    0 讨论(0)
  • 2020-12-15 15:43

    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
    
    0 讨论(0)
提交回复
热议问题