supposons le code Ruby suivant:
bank.branches do |branch|
branch.employees.each do |employee|
NEXT BRANCH if employee.name = "John Doe"
end
end
NEXT BRANCH est bien sûr un pseudocode. y a-t-il un moyen de sortir d'une boucle parent, comme en Perl, par exemple (en utilisant des étiquettes de boucle)?
merci d'avance.
Catch et lancer pourrait être ce que vous cherchez:
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
Il n'y a pas de moyen intégré pour sortir des blocs sans leur consentement. Vous devrez juste faire quelque chose comme:
bank.branches do |branch|
break unless branch.employees.each do |employee|
break if employee.name == "John Doe"
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
Mon impulsion serait de déplacer les blocs imbriqués dans une méthode, avec un return
à la place de 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
D'autres publications ont référencé une idée similaire à la création d'une variable "switch". Voir ci-dessous pour un exemple clair de son fonctionnement. Gardez à l'esprit que la seconde boucle sera toujours en cours d'exécution jusqu'à ce qu'elle atteigne la fin du tableau d'employés, mais n'exécutera aucun code après l'inversion du commutateur. Ce n'est pas la manière optimale de procéder car cela peut être inutilement coûteux en temps si votre groupe d'employés est grand.
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
Une fois le commutateur inversé, la matrice interne ne sera plus active et la boucle parente passera à la branche suivante avec la réinitialisation du commutateur. Il est évident que davantage de commutateurs peuvent être utilisés pour des cas plus complexes.
Edit: L’effet souhaité peut être obtenu beaucoup plus simplement en appelant break dans la boucle interne (ne met fin à cette boucle):
bank.branches do |branch|
branch.employees.each do |employee|
break if employee.name = "John Doe"
end
end
Voici ce que @steenslag était en train de rédiger avec 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
Votre exemple est donc:
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