Rubyのネストされたループでのbreakとthrowの使い方
今回は、ネストされたループで特定の条件を満たしたときにループを脱出する方法のbreak
とthrow&catch
の2つの違いを紹介します。
break
break
は、内側のループのみを脱出する際に使用します。外側のループは続行されるため、全ての組み合わせが試行されるまで処理が続きます。
以下のコードでは、vegetables
の配列とamounts
の配列をそれぞれシャッフルしながら繰り返し処理を行っています。vegetable
が'onion'
でn
が30
のときにbreak
を使って内側のループ(amounts)を脱出しますが、外側のループ(vegetables)は続行されます。
vegetables = ['cabbage', 'onion', 'eggplant']
amounts = [10, 20, 30]
vegetables.shuffle.each do |vegetable|
amounts.shuffle.each do |n|
puts "#{vegetable}, #{n}"
if vegetable == 'onion' && n == 30
break
end
end
end
# 出力例:
# onion, 10
# onion, 30 => ここでamountsのループは抜けるが、vegetablesのループが残っているので全パターン繰り返す
# eggplant, 20
# eggplant, 10
# eggplant, 30
# cabbage, 30
# cabbage, 10
# cabbage, 20
throwとcatch
一方、throw
とcatch
を使うと、特定の条件を満たした時点で全てのループを一気に脱出することができます。これを 大域脱出 と言います。
以下のコードでは、vegetables
の配列とamounts
の配列をそれぞれシャッフルしながら繰り返し処理を行っています。こちらも条件は同じく、vegetable
が'onion'
でn
が30
のときにループを脱出するようにします。
vegetables = ['cabbage', 'onion', 'eggplant']
amounts = [10, 20, 30]
catch :done do
vegetables.shuffle.each do |vegetable|
amounts.shuffle.each do |n|
puts "#{vegetable}, #{n}"
if vegetable == 'onion' && n == 30
throw :done
end
end
end
end
# 出力例:
# cabbage, 10
# cabbage, 30
# cabbage, 20
# onion, 10
# onion, 30 => この時点で、全てのループを脱出し処理が終了
まとめ
-
break
は内側のループを脱出するが、外側のループは続行される -
throw
とcatch
を使うと、全てのループを一気に脱出することができる