Как перерыв от вложенных циклов в Ruby?
предположим следующий код ruby:
bank.branches do |branch|
branch.employees.each do |employee|
NEXT BRANCH if employee.name = "John Doe"
end
end
NEXT BRANCH, конечно, псевдокод. есть ли способ, которым я могу выйти из родительского цикла, как это можно сделать в Perl, например (используя метки меток)?
заблаговременно.
Ответы
Ответ 1
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
Ответ 2
Нет встроенного способа выхода из блоков без их согласия. Вам просто нужно сделать что-то вроде:
bank.branches do |branch|
break unless branch.employees.each do |employee|
break if employee.name == "John Doe"
end
end
Ответ 3
while c1
while c2
# execute code
do_break = true if need_to_break_out_of_parent_loop
end
break if do_break
end
Ответ 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
Ответ 5
Edit:
Оказывается, желаемый эффект может быть достигнут гораздо проще, вызвав перерыв внутри внутреннего цикла (только завершит этот цикл):
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
Ответ 6
Другие сообщения ссылаются на идею, похожую на создание переменной "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
После переключения переключателя внутренний массив больше не будет активен, и родительский цикл переместится в следующую ветвь с помощью переключателя reset. Очевидно, что для более сложных случаев можно использовать больше коммутаторов.