Search

検索したいワードを入力してください

2019年03月21日

Rubyのwhileループを使う|基礎から応用まで解説

Rubyにはwhileループがあります。これは条件式が偽になるまで繰り返す構文です。このループはbreakによって途中で終了させたり、nextによってループをスキップさせたりすることができます。本記事では、これらの使い方について詳しく説明します。

while文とは

whileとは、条件式を指定して、条件式が真である間、繰り返しを行う文です。条件式はループの実行前に毎回判定され、whileの条件が偽になった時点でループが終了します。最初から条件式が偽の場合は1回も実行されません。

Rubyのwhile文の使い方

Rubyではwhile文というループ構文があります。ループは必ず条件が偽になるまで繰り返されるとは限らず、ある条件で途中で中断して終了することもできます。また、ある条件の時だけループ処理を行わないようにすることも可能です。

while文の基本的な書き方

whileの後に条件式を続けて、do ~ endのブロックを用いて記述を行います。ループ部分を見やすくするため、ブロック部分はインデントするのが普通です。ブロック部分をwhileと別の行に記述する場合には、doを省略できます。

while-do構文の例

以下のRubyスクリプトでは、1から10まで1行ごとに表示します。
i=1
while i<=10 do
puts i
i+=1
end

実行結果

1
2
3
4
5
6
7
8
9
10

外部テキストファイルを一行ずつ処理する

whileループは、外部テキストファイルを一行ずつ処理するのにも使うことができます。while gets ~でコマンドライン引数で指定ファイルを一行ずつ処理することができます。

何もコマンドライン引数を指定しない場合は標準入力から処理されます。ファイルの終端に達するとgetsで取得した値はnilとなるので、whileループが終了します。

whileを使ったテキストファイル処理の例

以下のRubyスクリプトでは、指定したテキストファイルに対し、項目番号をつけ、英単語の頭文字を大文字にします。

#*** gets.rb ***
while gets
puts format"(%2d) %s",$.,$_.capitalize
end

【fruits.txt】
apple
banana
orange
lemon

実行結果

$ ruby gets.rb fruits.txt
( 1) Apple
( 2) Banana
( 3) Orange
( 4) Lemon

Rubyワンライナーでは、-nオプションでwhile gets ~ end内の構文を引数に設定できるので、スクリプトを作成しなくても、ruby -ne 'puts format"(%2d) %s",$.,$_.capitalize'で同様の処理を行うことができます。

breakを使ってループを抜ける

break文は、条件式が偽にならなくても、ある条件を満たした時点でループの途中で中断して終了することができます。これは、ループをこれ以上継続する必要がないときに使われます。

breakの使い方

以下のRubyスクリプトでは、サイコロを6回投げ続けます。ただし、出た目の合計が20に達した時点で終了します。

#*** dice.rb ***
sum=0
count=1

while(count<=6)
dice=Random.rand(1..6)
sum+=dice
puts format"(%2d) サイコロの目:%d、合計:%2d",count,dice,sum
break if sum>=20
count+=1
end

実行結果

※実行するたびに異なる結果となります
$ ruby dice.rb
( 1) サイコロの目:4、合計: 4
( 2) サイコロの目:1、合計: 5
( 3) サイコロの目:1、合計: 6
( 4) サイコロの目:6、合計:12
( 5) サイコロの目:3、合計:15
( 6) サイコロの目:1、合計:16

$ ruby dice.rb
( 1) サイコロの目:4、合計: 4
( 2) サイコロの目:1、合計: 5
( 3) サイコロの目:6、合計:11
( 4) サイコロの目:5、合計:16
( 5) サイコロの目:6、合計:22

nextを使ってループをスキップ

nextを使うと、ある条件を満たしたときにそれ以降の処理を行わないで、次のループに移ることができます。C言語などではcontinueを使いますが、Rubyではnextを使うので注意してください。

ループの途中から全てifブロックで囲っても同様のことが実装できますが、nextのための条件式が連続する場合に、ifブロックを入れ子にする必要がなくなります。

nextの使い方

以下のRubyスクリプトでは、コマンドライン引数で指定したファイルに対し、#で始まるコメントは除外して行に番号付けを行います。

#*** next.rb ***
count=1
while gets
next if $_.strip.start_with?("#")
puts format("(%2d) %s",count,$_.capitalize)
count+=1
end

<テキストファイルfruits_comment.txt>
apple
banana
#Some comment
orange
#Some comment
lemon
#Some comment
peach
strawberry

実行結果

$ ruby next.rb fruits_comment.txt
( 1) Apple
( 2) Banana
( 3) Orange
( 4) Lemon
( 5) Peach
( 6) Strawberry

redoを使ってループを再実行

redoでは、再び始めからそのループを実行します。ある条件のときに複数回実行したいときに使用されます。redoはnextと似ていますが、その後に条件判定を挟まないでループの最初から行うという点が異なります。使用頻度は、breakやnextほど多くはありません。

redoの使い方

以下のRubyスクリプトでは、テキストに行単位で並んでいる整数の合計を求めます。文字列が整数として扱えない場合は、マッチングを行い、先頭から見て最初の数字列を、加算する整数とみなして、redoで再実行します。

#*** redo.rb ***
sum=0
count=0

while gets
begin
sum+=Integer($_)
count+=1
rescue
if m=$_.match(/\d+/)
$_=m[0]
redo
end
end
end

puts"有効データ数: #{count}"
puts"合計: #{sum}"

【nums.txt】
45
51
<32>
64
(21)
Comment
64
57

実行結果

有効データ数: 7
合計: 334

while文とfor文の違い

while文とfor文の大きな違いは、ループする回数があらかじめ決まっているかどうかです。whileは条件式を指定して、条件式が偽になるまで繰り返します。一方、forはfor i in <オブジェクト>というように、ある決まった大きさのデータの集合に対して処理を行います。

実は、breakを使ったサイコロを振るプログラムは、forループのオブジェクトに範囲演算子を使うことで実装できます。

#*** dice.rb ***
sum=0
#count=1 #削除

for i in 1..6 #変更
dice=Random.rand(1..6)
sum+=dice
puts format"(%2d) サイコロの目:%d、合計:%2d",count,dice,sum
break if sum>=20
#count+=1 #削除
end

外部でループカウンタを定義する必要がないので、whileより効率的に実装できます。ここで、無理にwhileを使おうとすると、count+=1を書き忘れて無限ループになる恐れもあります。whileはループする回数が、実行前にあらかじめ決まっていない場合に限って使用しましょう。

whileの逆の構文until

Rubyには、whileループとは逆に、条件が真になるまで処理を継続するuntilループがあります。whileで条件式を否定しても同じことが可能ですが、複雑な論理式の場合は、否定にすると意図がわかりにくくなるため、untilを使用するのが妥当です。

例えば、while(i!=0 && j!=0)until(i==0 || j==0)とも書けます。

条件式をループの途中で判定するには?

Rubyでは、loop文によるループを使うと、ループブロック内の任意の位置で終了条件を指定することができます。これはbreakがない場合は無限ループとなりますが、breakをブロックの途中に記述することで途中で処理を終了することができます。RubyにはC言語のようなdo ~ while構文はありませんが、loopブロックの末尾にbreakを記述すると、同様の構文が実装可能です。

サンプルコード

以下のRubyスクリプトでは、1以上100以下の整数を入力するとその整数を表示します。入力が整数でない場合や範囲外の場合は再度入力させます。

i=nil

loop do
print"1から100までの整数を入力してください: "
i=Integer(gets) rescue 0
break if (1..100)===i
end

puts"入力された整数は#{i}です"

実行結果

1から100までの整数を入力してください:
1から100までの整数を入力してください: foo
1から100までの整数を入力してください: 0
1から100までの整数を入力してください: 127
1から100までの整数を入力してください: 34
入力された整数は34です

while文を使った作例

数学の未解決(証明されていない)問題として、コラッツ(Collatz)予想があります。この予想は、任意の2以上の整数nについて、

(1)nが偶数であれば2で割る
(2)nが奇数であれば3を掛けて1を足す

この計算結果を新しいnとして、逐次繰り返すと、最終的にn=1になるという予想です。

以下のRubyスクリプトでは、整数nをコマンドライン引数で与えて、1になるまでwhileで計算を行います。

サンプルコード

#*** collatz.rb ***
n=Integer(ARGV[0]) rescue 0
abort"2以上の整数を指定してください" unless n>=2

count=1

while(n!=1)
print"(#{count.to_s.rjust(3)})#{n}は"

if(n%2==0) then
print"偶数より、#{n}/2"
n/=2
else
print"奇数より、#{n}*3+1"
n=3*n+1
end

print" = #{n}"
print"\n"
count+=1
end

実行結果

$ ruby collatz.rb 27
( 1)27は奇数より、27*3+1 = 82
( 2)82は偶数より、82/2 = 41
( 3)41は奇数より、41*3+1 = 124
( 4)124は偶数より、124/2 = 62
( 5)62は偶数より、62/2 = 31
( 6)31は奇数より、31*3+1 = 94
( 7)94は偶数より、94/2 = 47
( 8)47は奇数より、47*3+1 = 142
( 9)142は偶数より、142/2 = 71
( 10)71は奇数より、71*3+1 = 214

(中略)

(103)80は偶数より、80/2 = 40
(104)40は偶数より、40/2 = 20
(105)20は偶数より、20/2 = 10
(106)10は偶数より、10/2 = 5
(107)5は奇数より、5*3+1 = 16
(108)16は偶数より、16/2 = 8
(109)8は偶数より、8/2 = 4
(110)4は偶数より、4/2 = 2
(111)2は偶数より、2/2 = 1

意図に応じて適切な構文を選ぼう

Rubyのループでは、実行条件の他に、breakやnextなど、さらに条件式を付け加えることも可能です。ただし、実装する意図によって、while/until、if/unlessを使い分けないと読みにくくなります。

例えば、nextは「実行しない条件」を記述するので、「この条件のときのみ実行する」のであれば、「この条件でなければ実行しない」という意味でunlessを使用するのが読みやすいでしょう。

【PR】多くの人がプログラミングを諦めてしまう理由をご存知ですか?



近年プログラミングを勉強する人が増えています。

プログラミング学習者の多くは独学から取り組もうとしますが、だいたい80%ほどは3ヶ月も続かずに諦めてしまいます。早い人は1日目で。

多くの人がプログラミングを独学しようとして諦める理由は、次の3つ。
●モチベーションが維持できない
●エラーの原因・解決方法が分からない
●どう学習すればよいか分からない

TechBoostというプログラミングスクールでは、みんなと一緒にプログラミングをするのでモチベーションの維持ができ、分からないことがあればマンツーマンで教えてくれ、徹底的に研究された初心者向けの教材が揃っています。

TechBoostを卒業後、実際にエンジニアとして転職した方もいるほど。

本気でプログラミングを学びたい方は、一度無料のカウンセリングでご相談ください。プログラミングを嫌いになる前に。

tech boostについて

オーダーメイド型の学習コンテンツを提供する「tech boost」 は、エンジニアのキャリア支援に特化したサービスを複数展開している株式会社Branding Engineerが運営しているプログラミングスクールです。最短3ヶ月間で、未経験から『プログラミングの基礎』、『実際に業務で必要となるスキル』、『今のトレンドとなっている知識』まで学べ、ご希望の方にはプロのキャリアアドバイザーによる就業支援を行うことができます。

tech boost卒業生インタビュー

tech boostの卒業生の声を聞きました。あなたがプログラミングを学びたい理由を、一度考えてみてください。
営業→Javaエンジニア→Rubyエンジニアと転向し、第一志望のFinTech企業で働く山下さん
元営業、ビジネスのわかるエンジニアを目指す菅原さん
サンフランシスコに交換留学し、シリコンバレーのVCでインターン中の梅本さん
予備校の営業から半年でエンジニア転職を果たした小田島さん

tech boostの口コミ



Related