こんにちは!Webコーダー・プログラマーの貝原(@touhicomu)です。今日は、RubyのRangeオブジェクト(範囲オブジェクト)について解説します。この記事では、
- 範囲オブジェクトの指定方法
- Rangeクラスで範囲を指定する方法
- Rangeでeachを使う方法
- Rangeでforを使う方法
- 日付でRangeを使う方法
- 数値範囲オブジェクトでinclude?による比較
- 文字範囲オブジェクトでinclude?による比較
- 日付範囲オブジェクトでinclude?による比較
というように、基本的な内容から応用的な使い方に関しても学習していきます。このページで、RubyのRangeオブジェクト(範囲オブジェクト)の使い方をよく把握して自分のスキルとしていきましょう!
範囲オブジェクトの指定方法
まずは基本的なRangeの使い方について見てきます!Rangeは直訳すると「範囲」という意味ですが、Rangeオブジェクトはその通り範囲を表すためのオブジェクトです。
範囲オブジェクトはリテラルで指定します。リテラルとは、Rubyのプログラム中に直接書き込める値のことです。例えば数字の2や文字列”ruby”はリテラルです。というのも、値として直接解釈されるからです。
反対にprintなど直接「値」として解釈されないものはリテラルではないものです。擬似コードで範囲オブジェクトのリテラルを書くと、以下のような形になります。
範囲開始値..範囲終了値
以上のように、範囲の開始値と範囲の終了値を「..」でつないで書くと、範囲オブジェクトのリテラル表現になります。まずは、範囲オブジェクトをpメソッドで出力して、Rubyが範囲オブジェクトをどのように取り扱っているか確認してみましょう。
range = 1..10 p range
実行結果:
1..10
以上のように、「1..10」をオブジェクトであるものとRubyが認識し、pメソッドによりオブジェクトをそのまま出力しています。
範囲は数字だけではなく文字などでも使うことができます。
# 'a'から'z'までの範囲オブジェクトを出力 p 'a'..'z'
実行結果:
"a".."z"
以上のように、文字の範囲オブジェクトもRubyに正しく認識されています。
Rangeクラスで範囲を指定する
範囲オブジェクトは前述した「範囲開始値..範囲終了値」によってオブジェクトを作成できますが、Rangeクラスのnewメソッドでも同様に範囲を指定することができます。具体的には以下のように記述します。
range1 = Range.new(1, 10) range2 = Range.new('a', 'z') p range1 p range2
実行結果:
1..10 "a".."z"
このように「範囲開始値..範囲終了値」の場合と同じように範囲オブジェクトを定義できます。
繰り返しでRangeを使う
Rangeでeachを使う方法
範囲オブジェクト(Rangeオブジェクト)はeachによる繰り返しでよく使用されます。eachによる繰り返しを行いたい時は配列を渡していた方も多いと思いますが、範囲オブジェクトを渡すことで少し手間が省けます。
(1..5).each do |i| p i end
実行結果:
1 2 3 4 5
以上のように、範囲オブジェクトに直接eachメソッドを使用し、繰り返し処理を行うことができます。
また、範囲オブジェクトに対し、「1…5」と指定することで、最大値(ここでは5)を含まずに繰り返します。
# 1から10までの範囲オブジェクトを繰り返し出力(最大値を含まない) (1...5).each do |i| p i end
実行結果:
1 2 3 4
以上のように、「1…5」と少し形を変えて範囲オブジェクトを指定することで、最大値を含まない範囲オブジェクトになります。
eachメソッドについて詳しくは、以下の記事を参照してください。
Rangeでforを使う方法
範囲オブジェクト(Rangeオブジェクト)には、for文による繰り返し処理にも使用できます。for文の処理内容はeachメソッドと全く同じです。for文はeachメソッドで実現されています。
このように、for文のような他の言語でよく使う構文をeachと同じように使えるようにすることを、「Rubyのシンタックス・シュガー」と言います。
シンタックス・シュガーとは、「(Rubyの)構文を砂糖のように甘くてやさしく、柔軟性のある使い方にすること」という意味です。
実際に文字の範囲オブジェクトにfor文を使ってみましょう。ここでは、’a’から’d’までのアルファベットの範囲オブジェクトを使用します。
for i in 'a'..'d' p i end
実行結果:
"a" "b" "c" "d"
以上のように、範囲オブジェクトに対してeachメソッドの場合と同じようにfor文が使用できました。
for文について詳しくは、以下の記事を参照してください。
日付でRangeを使う方法
日付もRangeオブジェクトとして扱うことができます。このおかげで連番の日付を、簡単に生成することができます。
ここでは、Dateクラスのparseメソッドを使用して、”2017-03-01”などの文字列からDateクラスのインスタンス(値)を作成しています。
そして、日付の範囲オブジェクトに対し、eachメソッドを使用して範囲の分、日を繰り返して、pメソッドによりそれぞれの日を出力しています。
require 'date' (Date.parse("2017-03-01")..Date.parse("2017-03-05")).each do |date| p date end
実行結果:
#<Date: 2017-03-01 ((2457814j,0s,0n),+0s,2299161j)> #<Date: 2017-03-02 ((2457815j,0s,0n),+0s,2299161j)> #<Date: 2017-03-03 ((2457816j,0s,0n),+0s,2299161j)> #<Date: 2017-03-04 ((2457817j,0s,0n),+0s,2299161j)> #<Date: 2017-03-05 ((2457818j,0s,0n),+0s,2299161j)>
Dateについて詳しくは、以下の記事を参照してください。
Rangeでinclude?による比較
Rangeの中に値が含まれているかどうかをinclude?メソッドで確かめることができます。
include?メソッドはRangeオブジェクトに共通のメソッドで、数値のRangeオブジェクト、文字のRangeオブジェクト、日付のRangeオブジェクトのどれにも適用できます。
数値Rangeオブジェクト
まずは、数値のRangeオブジェクトに対して、include?メソッドを使用してみましょう。include?は、第一引数に値を指定すると、その値がRangeオブジェクトに含まれている場合はtrue、含まれてない場合はfalseを返します。
range = 1..5 p range.include? 3 p range.include? 8
実行結果:
true false
文字Rangeオブジェクト
次に、文字のRangeオブジェクトに対してinclude?メソッドを使用してみましょう。構文は数値のRangeオブジェクトのinclude?メソッドと同じ構文です。
range = 'a'..'d' p range.include? 'b' p range.include? 'z'
実行結果:
true false
日付Rangeオブジェクト
次に、日付のRangeオブジェクトに対してinclude?メソッドを使用してみましょう。構文は数値のRangeオブジェクトのinclude?メソッドと同じ構文です。
require 'date' p (Date.parse("2017-03-01")..Date.parse("2017-03-05")).include? Date.parse("2017-03-03") p (Date.parse("2017-03-01")..Date.parse("2017-03-05")).include? Date.parse("2017-04-01")
実行結果:
true false
以上のように、日付Rangeオブジェクトに対してもinclude?を使用することができました。このようにRangeオブジェクトなら中身に関係なくinclude?による比較ができていることがわかります。
まとめ
今回は、RubyのRangeオブジェクト(範囲オブジェクト)について学習しました。学習のポイントを振り返ってみましょう!
- Rangeオブジェクトには、数値、文字、日付などの範囲を指定できる
- each繰り返しでRangeを使うことができる
- for繰り返しでRangeを使うことができる
- include?によりRangeオブジェクトの比較ができる
以上の内容を再確認し、ぜひ自分のプログラムに生かし学習を進めてください!