繰り返し処理の種類
for~要素を取り出して処理する
Range
オブジェクトを使った繰り返し処理。".."
演算子は両端の値を含む。
1 2 3 4 5 6 |
for n in 0..5 do print(n, " ") end puts # 0 1 2 3 4 5 |
"..."
演算子は終了値を含まない。
1 2 3 4 5 6 |
for n in 0...5 do print(n, " ") end puts # 0 1 2 3 4 |
配列の内容を一つずつ取り出す例。
1 2 3 4 5 6 |
for n in ["A", "B", "C", "D"] do print n, " " end puts # A B C D |
times~回数を指定する処理
times
は繰り返し回数を指定して実行。
1 2 3 4 5 6 |
5.times do print "はい" end puts # はいはいはいはいはい |
繰り返しのカウンターを指定できる。カウンターはゼロからスタートし、指定回数-1までカウントされる。
1 2 3 4 5 6 |
5.times do |n| print n, " " end puts # 0 1 2 3 4 |
upto/downto~カウントアップ/ダウン
upto
は初期値から終了値までを含んでカウントアップ。downto
は逆にカウントダウン。カウンターを省略しても可。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
1.upto(5) do |n| print n, " " end puts # 1 2 3 4 5 5.downto(1) do |n| print n, " " end puts # 5 4 3 2 1 |
step~刻み幅を指定
[初期値].step([終了値], [刻み幅])
で実行。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
1.5.step(4.0, 0.5) do |n| print n, " " end puts # 1.5 2.0 2.5 3.0 3.5 4.0 1.0.step(-1.0, -0.5) do |n| print n, " " end puts # 1.0 0.5 0.0 -0.5 -1.0 |
終了値がちょうどでない場合はその手前まで実行される。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
1.5.step(4.0, 0.75) do |n| print n, " " end puts # 1.5 2.25 3.0 3.75 2.0.step(-1.5, -0.75) do |n| print n, " " end puts # 2.0 1.25 0.5 -0.25 -1.0 |
ただし浮動小数点の計算誤差があり得るので、ちょっと気持ち悪い。
each~要素を一つずつ取り出す
each
はfor
と同じくコレクションの要素を順に取り出す。
1 2 3 4 5 6 7 8 |
[0, 1, 2, 3].each do |n| puts(n) end # 0 # 1 # 2 # 3 |
hashはキーと値を取り出せる。
1 2 3 4 5 6 7 |
{FL:"Florida", IA:"Iowa", OH:"Ohio"}.each do |key, value| puts "#{key} is abbreviation of #{value}" end # FL is abbreviation of Florida # IA is abbreviation of Iowa # OH is abbreviation of Ohio |
ブロックの省略形{...}
がある。
1 2 3 4 5 |
[0, 1, 2, 3].each { |n| puts(n) } # 0 # 1 # 2 # 3 |
each_with_index~要素番号も取得
each_with_index
はコレクションから要素を取り出しながら、そのインデックスも得られる。Pythonのenumerate
と同じ機能。
1 2 3 4 5 6 7 8 |
["A", "B", "C", "D"].each_with_index do |element, index| puts "#{index} - #{element}" end # 0 - A # 1 - B # 2 - C # 3 - D |
while~条件が真の間繰り返し
while
は条件が真の間ブロックを繰り返す。
1 2 3 4 5 6 7 8 |
n = 0 while n < 5 do print n, " " n += 1 end puts # 0 1 2 3 4 |
while
をbegin
…end
ブロックの後に置ける。上記の前置の場合は条件によってはブロックは一度も実行されないが、後置の場合は少なくとも1回は実行される。
1 2 3 4 5 6 7 8 |
n = 0 begin print n, " " n += 1 end while n < 5 puts # 0 1 2 3 4 |
until~条件が真になるまで繰り返し
until
はwhile
と逆で条件が偽の間繰り返し、真になったらループ終了。while
と同様、ブロックの前/後どちらに置いてもよい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
n = 0 until n >= 5 do print n, " " n += 1 end puts # 0 1 2 3 4 n = 0 begin print n, " " n += 1 end until n >= 5 puts # 0 1 2 3 4 |
loop~無限ループ
loop
は単にブロックを繰り返す。ループの終了判定が必要。
1 2 3 4 5 6 7 8 9 |
n = 0 loop do print n, " " n += 1 break if n >= 5 end puts # 0 1 2 3 4 |
繰り返し制御
break~ループを終了
break
は実行中のループブロックを終了する。
1 2 3 4 5 6 7 |
for n in 0...5 do print n, " " break if n == 3 end puts # 0 1 2 3 |
next~残りを飛ばして続ける
next
はそれ以下の実行をせず、ループの次のステップに入る。他言語のcontinue
と同じ。
以下の例ではn==2
のときだけprint
が実行されず、次のn=3
の処理に入る。
1 2 3 4 5 6 7 |
for n in 0...5 do next if n == 2 print n, " " end puts # 0 1 3 4 |
redo~同じ条件で再実行
redo
は現在のループと同じ条件で再度実行する(ループの次のステップではなく同じステップを再実行)。
1 2 3 4 5 6 7 8 9 10 11 12 |
n = 0 ["A", "B", "C", "D"].each do |a| puts "#{n} - #{a}" n += 1 redo if n == 3 end # 0 - A # 1 - B # 2 - C # 3 - C # 4 - D |
この例では、n==2
の時に"2 - C"
を表示。その後n==3
となってredo
が実行され、a=="C"
のままputs
から実行、"3 - C"
が表示されている。
次の例はすこしややこしい。
1 2 3 4 5 6 7 8 |
[0, 1, 2, 3].each do |n| print n n += 1 redo if n == 2 end puts # 01223 |
この例ではeach
でn=1
とセットされて"1"
が表示される。その後n==2
となるのでredo
が実行され、n==2
のままprint
が実行されて"2"
が表示。その後n==3
になるので次のeach
に移り、n==2
がセットされる。このn("2")
を表示した後、n==3
となるのでredo
は実行されず・・・と続く。