Rubyのtimesメソッドを使って繰り返し処理を行う方法
Rubyのtimesメソッドとは
timesメソッドとは、回数を指定する繰り返し処理です。Rubyの繰り返し処理に代表されるeachメソッドはコレクションの要素をすべて走査し、whileやforはある条件が満たされている間処理を続けます。timesメソッドの特徴は何回繰り返しを行うか、回数を指定する点です。
最もよく使われる場面としては、年や月、日にちに対してそれぞれ処理を施したいときや、テスト用データをとりあえず5個作りたいなどが挙げられます。本記事ではtimesメソッドの基本的な使い方や、timesに似たupto・downtoメソッド、その他の繰り返し処理についても復習していきます。
timesメソッドの基本的な書き方
timesメソッドはIntegerクラスで定義されており、整数に対して呼び出すことができます。
5.times do
何か処理
end
このように書くとブロック(do ~ end)を5回実行してくれます。ブロックの書き方については、do ~ endと書く場合と、{ ~ } を使って書く場合があるのですが、1行で書く場合は{}を使い、複数行になる場合はdo ~ end を使うようにしましょう。
5.times { 1行で書ける処理 }
5.times do
複数行の処理
end
ブロックの書き方については、timesメソッド以外でもRubyのコードでブロックを書く場合は1行なら{},複数行ならdo ~ endを使うように統一しましょう。
timesメソッドの使い方
もう少し詳しくtimesメソッドの使い方を見ていきます。変数nに整数値が入っているとして、timesメソッドを書いてみると
n.times do
p "処理を行いました"
end
となります。処理の中で現在の繰り返し回数を取得することもできます。
n.times do |i|
p "#{i + 1}回処理を行いました"
end
これまでRubyでeachメソッドを使ったことがある方ならこの書き方には既に慣れているでしょう。|i|のiはブロック変数(またはブロックパラメータともいう)と言い、ブロックの内部でのみ使用できる変数です。timesのブロック変数は0から始まり、繰り返しごとに1ずつ増えていきます。そのため、現在の繰り返し回数を表示する場合は、1を足した数を用いています。
0以下の整数(0, -1, ...)に対してはブロックの中身は一度も実行されません。1以上の整数値に対してのみ、その数値回数ブロックを実行します。
timesメソッドを使ったサンプルコード
引数に西暦年を渡すと、その年の1月から12月の日数を返すメソッドをtimesメソッドを使って書いてみます。
require 'date'
def days_count_in(year)
days = [0]
12.times do |i|
month = i + 1
days.push Date.new(year, month, -1).day
end
days
end
> days = days_count_in 2019
> days[2]
28
> days[12]
31
特に解説が必要な部分はありませんが、1点だけ、Date.newの第三引数に-1を渡すと月末の日にちを返してくれます。あまり知られていませんが、月末の日付は何かと使うので便利です。
uptoメソッドの使い方
timesメソッドに似たメソッドでuptoというものがあります。uptoはある数値からある数値まで1ずつ増えながらループを繰り返すメソッドです。早速使い方を見ていきましょう。
> 5.upto(10) {|i| p i}
5
6
7
8
9
10
「5 upto 10」をGoogle翻訳で日本語に直すと「5から10まで」という意味になります。この英文の順番に「開始数.upto(終了数)」と書けばいいので、とても直観的にコーディングできます。
終了数が開始数より小さいときはブロックを一度も実行しません。また、timesメソッドとは異なり、開始数、終了数ともに0や負の整数(-1, -2,...)も指定することができます。
downtoメソッドの使い方
downtoメソッドはuptoメソッドの真逆で、ある数値からある数値まで1ずつ減りながら繰り返しを行います。uptoメソッドを理解できた方なら、downtoメソッドも容易に理解することができます。
簡単に使い方を見ていきましょう。
> 10.downto(5){|i| p i}
10
9
8
7
6
5
times,upto,downtoを使って配列を作る
これまでtimes,upto,downtoの使い方を見てきましたが、これらのメソッドの面白い使い方を紹介します。実は、times,upto,downtoにブロックを渡さないと、これらのメソッドは列挙(Enumerator)オブジェクトを返します。EnumeratorはEnumerableモジュール(Rubyの繰り返しに関するメソッドを定義)の機能をクラスとして使えるようにしたラッパークラスです。
さて、このEnumeratorオブジェクトは、to_aメソッドにより配列へ変換することができます。なので、次のようにtimes,upto,downtoメソッドから配列を作ることができます。
> enum = 5.times
> enum
#
> enum.to_a
[0, 1, 2, 3, 4]
> 5.upto(10).to_a
[5, 6, 7, 8, 9, 10]
> 10.downto(5).to_a
[10, 9, 8, 7, 6, 5]
その他の繰り返し処理
これまで数値を使った繰り返し処理を見てきましたが、その他のRubyで使える繰り返し処理についても見ていきましょう。Rubyではほとんどの場合eachとwhile(またはuntil)さえ覚えておけば問題なく繰り返し処理を行うことができるのですが、いろいろな書き方を知っておくのも重要です。
for文
forは繰り返し処理ができる(eachが使える)オブジェクトに対して、順番に要素を取り出し繰り返し処理を行うメソッドです。使い方を見ていきましょう。
> for i in [5,6,7,8,9,10] do
> p i
> end
> for item in {name: "apple", price: 100 }do
> p item
> end
[:name, "apple"]
[:price, 100]
最後の例ではハッシュのキー・バリューの組を順番に取り出しました。実は、ハッシュの場合にはもっといい書き方があります。
> for key, value in {name: "apple", price: 100 }do
> p "#{key} is #{value}"
> end
"name is apple"
"price is 100"
for~inの間に二つ変数を置くことで、キー・バリューがそれぞれ代入されます。
eachメソッド
eachメソッドはおそらくRubyの数ある繰り返しの中で最もよく使われます。eachメソッドはforと同じくリストやハッシュの中身を順番に取り出します。使い方を見ていきましょう。
> [1,2,3,4,5].each do |i|
> p i
> end
1
2
3
4
5
ハッシュに対しては、forと同じように、キー・バリューをそれぞれ個別に取り出すことができます。
{name: "apple", price: 100 }.each do |key, value|
p "#{key} is #{value}"
end
Rubyの入門書ではforではなく、繰り返しといえばeachを使う方が多いです。後述しますが、Rubyではforとeachは決定的に異なる部分があり、その差でほとんどの場合eachが使用されます。
eachとforの違い
forとeachを説明しましたが、一体何が違うのでしょうか。答えは、リストやハッシュの各要素を保存しておく変数の扱い方にあります。forでは繰り返しに用いる変数がブロック内にとどまらず、グローバルな変数となってしまいます。
> for i in [1,2] do
> p i
> end
> i
3
一方、eachは繰り返しに用いた変数がブロックの中にとどまります。
> [1,2].each do |i|
> p i
> end
> i
NameError: undefined local variable or method `i' for main:Object
eachで使用したiを参照しようとすると、定義されていないという旨のエラーが発生しました。明確な意図があればいいですが、eachの方が繰り返しのために使う変数をブロックの中に留めておくという点で安全です。したがってRubyでリストなどを繰り返し処理するときはeachを使いましょう。
while文
whileは指定した条件が真(true)の間ブロックの処理を繰り返し実行します。forやtimesと異なり、容易に無限ループを起こしやすいので注意が必要です。使い方を見ていきましょう。
user= nil
index = 0
while user== nil do
if users[index] && users[index].name == "Alice"
user= users[index]
elsif users[index] == nil
user= User.new("Alice")
end
index += 1
end
この例では、ユーザのリストを上から順番に走査し、見つかればresultにユーザを、見つからなければ新しくユーザを作成しています。resultやindexの更新を忘れてしまうと無限ループになってしまうので、whileを使うときは注意が必要です。
until文
untilはwhileと真逆の動き方をします。untilは指定した条件式が偽(false)の間処理を繰り返します。使い方を見ていきましょう。
user = nil
index = 0
until user do
if users[index] && users[index].name == "Bob"
user = users[index]
elsif users[index] == nil
user = User.new("Tom")
end
index += 1
end
whileのサンプルと似ていますが、こちらはuserが見つかるか、リストの最後まで到達して新しくユーザが作られるまで繰り返しが続きます。untilに渡す条件式は「終了条件」、whileに渡す条件式は「継続条件」と覚えるといいでしょう。
untilとwhileの使い分けは難しいですが、「~の時終了する」ならuntil、「~のあいだ繰り返す」ならwhileというように使い分けます。
loopメソッド
最後に紹介するRubyの繰り返しはloopメソッドです。loopに終了条件などはなく、必ずbreakでループを止める必要があります。breakはループ処理を中断し、終了する構文で、timesやfor,each,while,untilでも使うことができます。ではloopの使い方を見ていきましょう。
loop do
puts "input text:"
text = gets.to_s.chomp
if text == 'exit'
break
else
puts "input: #{text}"
end
end
この例は、画面からの入力に対して「exit」という文字なら実行を終了し、それ以外なら画面に表示するサンプルコードです。コードをファイルに記述して保存し、「ruby 〇〇.rb」で実行してみてください。
Railsなどのウェブアプリ開発ではあまり使うことはありませんが、対話的なプログラムを作るときによく使います。
特徴をとらえて最も適したものを選ぼう
これまで見てきたようにRubyには多くの繰り返し文・メソッドが存在します。それぞれに特徴があり、特徴を的確にとらえて場面に応じた文・メソッドを選択することで、読みやすく、意図が伝わりやすいコードになります。
しかし、whileやuntil,loopは無限ループを起こしやすく、容易にバグを作ってしまうので、確かに繰り返しが止まるということをいろいろなパターンで確認して使うようにしましょう。
【PR】多くの人がプログラミングを諦めてしまう理由をご存知ですか?
近年プログラミングを勉強する人が増えています。
プログラミング学習者の多くは独学から取り組もうとしますが、だいたい80%ほどは3ヶ月も続かずに諦めてしまいます。早い人は1日目で。
多くの人がプログラミングを独学しようとして諦める理由は、次の3つ。
●モチベーションが維持できない
●エラーの原因・解決方法が分からない
●どう学習すればよいか分からない
TechBoostというプログラミングスクールでは、みんなと一緒にプログラミングをするのでモチベーションの維持ができ、分からないことがあればマンツーマンで教えてくれ、徹底的に研究された初心者向けの教材が揃っています。
TechBoostを卒業後、実際にエンジニアとして転職した方もいるほど。
本気でプログラミングを学びたい方は、一度無料のカウンセリングでご相談ください。プログラミングを嫌いになる前に。
tech boostについて
オーダーメイド型の学習コンテンツを提供する「tech boost」 は、エンジニアのキャリア支援に特化したサービスを複数展開している株式会社Branding Engineerが運営しているプログラミングスクールです。最短3ヶ月間で、未経験から『プログラミングの基礎』、『実際に業務で必要となるスキル』、『今のトレンドとなっている知識』まで学べ、ご希望の方にはプロのキャリアアドバイザーによる就業支援を行うことができます。
tech boost卒業生インタビュー
tech boostの卒業生の声を聞きました。あなたがプログラミングを学びたい理由を、一度考えてみてください。
営業→Javaエンジニア→Rubyエンジニアと転向し、第一志望のFinTech企業で働く山下さん
元営業、ビジネスのわかるエンジニアを目指す菅原さん
サンフランシスコに交換留学し、シリコンバレーのVCでインターン中の梅本さん
予備校の営業から半年でエンジニア転職を果たした小田島さん
tech boostの口コミ
TechBoostお金を払ったかいがあってすごく手厚いサービスで今のところすごく満足。
— Yatsushi@将来宇宙旅行します (@yatsushiGUN) 2019年1月18日
今日もスクールに通ってる人同士の交流会みたいなのもあってすごく有意義に過ごせた。#techboost#プログラミング
@tech_boost のカウンセリング完了!
— kinsu (@waraiotoko8) 2018年8月17日
いやー、ノウハウの宝庫!
カウンセリングだけでも凄い収穫!
プログラミングだけではなく起業や転職支援についても色々聞けた。
即断即決!その場で申し込み完了。
遅くても来年の春までに起業します!
僕の場合、これが現実的な最適解!
全てが楽しみだー!