ループ処理をスキップ・中断する方法などについても知りたい
どうも、フリーエンジニアの長瀬です。
Rubyのループの処理は配列やハッシュのメソッドまで含めると多くの種類があります。その中にはとても強力で便利なものもたくさんあるので、今のうちにいつでも使えるようにしておきましょう。
この記事では、配列やハッシュのループについて「基礎的ループ」を8つと、「発展的なループ」で「next」「redo」「break」などの特殊メソッドや、配列、ハッシュのループメソッドを解説していきます。
Rubyの基本的なループ処理
for
まずはおなじみfor文からです。
for文は基本的に指定した範囲オブジェクトの範囲分同じ処理を繰り返したり、配列の要素を順番に取得したい場合に使用します。
例えば範囲オブジェクトを指定する場合は、
for num in 1..5 do p num end
[実行結果]
1 2 3 4 5
この処理では範囲オブジェクトを「1..5」で指定していますので処理を5回繰り返しています。
範囲オブジェクトについて理解が浅いと感じる方はこちらの記事を一読することをおすすめします。
また、配列の中身を順番に出力したい時は以下のように記述します。
for num in [1,2,3,4] do p num end
[実行結果]
1 2 3 4
このように範囲オブジェクトの代わりに配列を記入すれば、出力することができます。
for文については、以下の記事でも詳しく解説しています。
each
先ほどfor文を解説しましたが、for文は実は配列のループではあまり使われません。
よく使用されるのは「eachメソッド」です。
eachメソッドは配列や範囲オブジェクトで使用できるメソッドで、オブジェクトに含まれる要素を順番に取得することができます。
配列の場合は
[1,2,3,4].each do |num| p num end
[実行結果]
1 2 3 4
ハッシュの場合は
{ruby:"rails",php:"Cakephp",python:"Django"}.each do |k,v| p "#{k}はkey、#{v}はvalue" end
[実行結果]
"rubyはkey、railsはvalue" "phpはkey、Cakephpはvalue" "pythonはkey、Djangoはvalue"
このようにfor文と似ていますが、書き方や英語の意味的にも直感的なため、配列の場合、実際の開発ではよくeachが使用されます。
while
whileでは指定した条件がtrueである間ループします。
for文は指定した要素分繰り返し処理を行うのに対して、while文は条件式がfalseになるまで処理を繰り返し行います。
num = 0 while num <= 12 do p num num += 3 end
[実行結果]
0 3 6 9 12
上記の例ようにnumに値をループのたびに加算して、 num<=12がfalse になったときにループが終了するようにしています。
また、whileはこのようにも書けます。
num = 0 while num <= 5 p num num += 1 end
[実行結果]
0 1 2 3 4 5
こちらの書き方では、doを省略しています。
until
untilでは指定した条件がfalseである間ループします。
whileが条件がtrueの間繰り返すのに対して、こちらはfalseの間繰り返すメソッドになります。
num = 16 until num <=12 do p num num -=1 end
[実行結果]
16 15 14 13
このように、num <=12 を満たした瞬間にループが終了しました。
loop
loopを使えば、breakでループを終了させない限りループし続ける処理を実装できます。
num =0 loop{ p num num+=3 if num >= 12 break end }
[実行結果]
0 3 6 9
さきほどのwhileと同じ処理を実装していますが、loopの場合はifである条件に達したらbreakで抜けています。
またloopはこのようにも書けます。
num =0 loop do p num num +=1 if num >= 3 break end end
[実行結果]
0 1 2
times
任意の回数ループさせるときにはtimesが便利です。指定した回数分だけループさせることができます。
3.times do |num| p num end
[実行結果]
0 1 2
始めの数字の部分(今回は3)を変えれば、任意の回数ループさせることができます。
なので、timesはこのようにも書けます。
5.times do p "ループしてます。" end
[実行結果]
"ループしてます。" "ループしてます。" "ループしてます。" "ループしてます。" "ループしてます。"
upto、downto
uptoは指定した数に到達するまでループで、その間に変数が1ずつ増加します。
downtoは名前のとおりuptoの反対で指定した数に到達するまでループで、その間に変数が1ずつ減少します。
[uptoの場合]
1.upto(3) do |num| p num end
[実行結果]
1 2 3
[downtoの場合]
3.downto(1) do |num| p num end
[実行結果]
3 2 1
名前も直感的で非常にわかりやすいメソッドです。
step
さきほど紹介したtimesでは、実は任意の整数しか指定できませんでしたが、stepを使えば少数も扱えます。
3.6.step(6.0,1.2) do |num| p num end
[実行結果]
3.6 4.8 6.0
このように、6.0まで1.2ずつを3.6を増加させるループを実装できました。
また、stepはこのようにも書けます。
1.1.step(1.5,0.1) do p "stepよるループの最中です。" end
[実行結果]
"stepよるループの最中です。" "stepよるループの最中です。" "stepよるループの最中です。" "stepよるループの最中です。" "stepよるループの最中です。"
prime
任意の数までの素数を出力したい場合にはPrimeが便利です。
require 'prime' Prime.each(11) do |num| p num end
[実行結果]
2 3 5 7 11
このように任意の数までの素数の個数分だけループできます。
また、Primeはこのようにも書けます。
require 'prime' Prime.each(7) do p "Primeによるルーブを実行しています。" end
[実行結果]
"Primeによるルーブを実行しています。" "Primeによるルーブを実行しています。" "Primeによるルーブを実行しています。" "Primeによるルーブを実行しています。"
ちょうどう7まで、4個の素数があるので、4回のループになりました。
素数の数でループの回数が決まるっておしゃれですよね。
発展的なループ
途中からループ内の処理をスキップ
nextを使えば、それ以降の処理を飛ばしてループを続けられます。
[1,2,3,4].each do |num| next if num ==1 p num end
[実行結果]
2 3 4
このように1の時はnext以降の「p num」が飛ばされて、1が出力されないことを確認できます。
途中からもう一度ループをやり直す
redoを使えば、もう一度そのループの始め方処理を繰り返すことができます。
[0,1,2,3,4].each do |num| num += 1 p num redo if num == 1 end
[実行結果]
1 2 2 3 4 5
このように2が2回繰り返されています。
これはnum==1 のときにredoが働いてもう一度そのループを始めから読み込んだからです。
途中でループを抜ける
次は途中からループを抜けてみましょう。
途中からループを回すのと同じく、条件分岐で書いていきます。
[1,2,3,4].each do |num| break if num ==3 p num end
[実行結果]
1 2
このように、breakを使えば、ループを任意のタイミングで抜け出すことができます。
複数個でループする
「二個ずつループを回したい!」や「二個ずつずらしてループを回したい」というのはよくあることです。
そんな時に役に立つのが「each_sliceメソッド」と「each_consメソッド」です!
まず、「each_sliceメソッド」について解説していきます。
each_sliceは引数に与えられた数ずつループを回します。
[1,2,3,4].each_slice(2) do |num| p num end
[実行結果]
[1, 2] [3, 4]
このように配列で二個ずつのループになっていることがわかります。
次に[1,2],[2,3],[3,4]という風に、二個ずつずらしてループを回す方法について紹介します。
その時に使用するのが「each_consメソッド」です。
[1,2,3,4].each_cons(2) do |num| p num end
[実行結果]
[1, 2] [2, 3] [3, 4]
このように二個ずつずらしてループになっていることがわかります。
インデックスをとりながらループ
eachで回すと、インデックスを取ることはできません。インデックスを取りたい時はeach_with_indexメソッドを使用する必要があります。
[1,2,3,4].each_with_index do |num, i| p num p i end
[実行結果]
1 0 2 1 3 2 4 3
このようにインデックスを取れていることがわかります。
その他ハッシュや配列のループまとめ
ハッシュのeachを使ったループメソッドはこちらにまとめられていますので、参考にしてみてください。
こちらの記事では配列とハッシュで使える繰り替えしメソッドを数多く紹介しています。
まとめ
いかがでしたでしょうか?
この記事では、配列やハッシュのループを解説しました。
基本的なループには
- for
- each
- while
- loop
- times
- upto
- downto
- step
- prime
と計8個のループがありましたね。
機能が重複している部分もありますが、それぞれ個性があるのでここぞという場面で使用していきたいですね。
また、その他の配列やハッシュで用意されているメソッドを含めるとRubyのループ処理の数がとても多く表現が豊かだということに驚かされます。
早い段階で覚えておいて損はないので、ぜひ自分でコードを叩いて試してみてください。
もし配列やハッシュのループ処理について忘れてしまったらこの記事を確認してくださいね!