switch rails objetos manejo lista instanciar importar clases ciclos ruby loops nested-loops

rails - ¿Cómo romper con los bucles anidados en Ruby?



manejo de objetos en ruby (6)

Mi impulso sería mover los bloques anidados en un método, con un return en lugar de la 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

asumir el siguiente código ruby:

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

NEXT BRANCH es, por supuesto, pseudocódigo. ¿Hay alguna forma de que pueda salir de un bucle principal, como se puede hacer en Perl, por ejemplo (mediante el uso de etiquetas de bucle)?

gracias por adelantado.


No existe una forma integrada de romper bloques que contienen sin su consentimiento. Tendrás que hacer algo como:

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


Otras publicaciones han hecho referencia a una idea similar a la creación de una variable "cambiar". Vea a continuación un claro ejemplo de cómo funciona. Tenga en cuenta que el segundo bucle seguirá ejecutándose hasta que llegue al final de la matriz de empleados, pero no ejecutará ningún código una vez que se haya volteado el interruptor. Esta no es la forma óptima de hacerlo, ya que puede ser innecesariamente costoso si su matriz de empleados es grande.

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

Después de que el interruptor se voltea, la matriz interna ya no estará activa y el bucle principal se moverá a la siguiente bifurcación con el restablecimiento del interruptor. Obviamente, se pueden usar más interruptores para casos más complejos.


Atrapar y arrojar puede ser lo que estás buscando:

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


Editar: El efecto deseado, resulta, se puede lograr de una forma mucho más simple llamando a la ruptura dentro del ciclo interno (solo terminará ese ciclo):

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

Esto es lo que @steenslag estaba escribiendo con 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

Entonces tu ejemplo es:

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


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