Rubyで繰り返し処理を作ろうとした場合、範囲オブジェクトとRangeクラスのメソッドを利用できます。さらに範囲オブジェクトは文字コードや日付など、範囲があるもののチェックにも利用可能です。
このように範囲オブジェクトを利用することで、範囲を利用したいろいろなプログラムの作成が可能です。とはいえ範囲のオブジェクトと言われてもよくわからないという方もいるでしょう。今回はRubyにおける範囲オブジェクトとRangeクラスについて解説します。
範囲オブジェクトという考え方
Rubyではプログラムの中で使用する全ての操作対象をオブジェクトとして扱います。数字や文字列、配列などは全てオブジェクトですし、範囲もRubyではオブジェクトとして扱います。
さらにRubyでは範囲をオブジェクトとして扱うことで、その範囲内で何かを処理するプログラムを作ることが可能です。そしてRangeクラスには範囲を扱うメソッドが定義されています。
範囲オブジェクトとは
範囲オブジェクトとは、文字どおりある範囲を扱うためのオブジェクトです。例えばある数字から別の数字までの範囲をオブジェクトで扱うということで、具体的に1から10まで範囲をオブジェクトにできます。
なおRubyでは全てのオブジェクトが特定のクラスに属しており、クラスにはそのオブジェクトに適用できるメソッドが幾つも定義されています。範囲オブジェクトはRangeクラスに属しており、Rangeクラスに含まれるメソッドで利用可能です。
Rangeクラス
Rangeクラスは、Rubyに標準で組み込まれているライブラリの1つで、範囲オブジェクトを扱うためのクラスです。数字の範囲の他、日付の範囲や文字コードによる範囲などが扱えます。また、Rubyの2.6.0以降なら終端を持たない範囲オブジェクトを作ることも可能です。
範囲オブジェクトは、特定の範囲内の繰り返し処理や、特定の範囲内に含まれているかのチェックなどで使えます。同じような処理は構造化プログラミングの書き方でも可能ですが、範囲オブジェクトを利用すればRubyらしいオブジェクト指向言語の書き方が可能です。
範囲オブジェクトの作成方法
Rubyでプログラムを書く際、クラスを意識する必要はありますが、変数の型を意識する必要はありません。変数に値を代入するとRubyが値のクラスを判定して自動的に該当するクラスに割り当てます。またnewメソッドでクラスを指定して変数を作ることも可能です。
範囲オブジェクトを新規に作成する場合も変数に範囲を含む値を代入するか、Rangeクラスのnewメソッドで作成するかのどちらからです。次に範囲オブジェクトの作成方法を紹介します。
「..」演算子を使用する
範囲オブジェクトを作成する際によく使われるのが「..」演算子です。「..」演算子の左辺に最初の値を指定し、右辺に最後の値を指定することで範囲を指定できます。
「..」演算子の使い方
最初の値 .. 最後の値
「..」演算子の例
range1 = 1..10 # 1から10までの範囲を持つ範囲オブジェクトrange1を作成 range2 = 'a'..'j' # 文字a1から文字jまでの範囲を持つ範囲オブジェクトrange2を作成
Range.newメソッドを使う
範囲オブジェクトは、Rangeクラスのnewメソッドで最初の値と最後の値を指定しても作れます。Rangeクラスのnewメソッドの文法は次のとおりです。
Rangeクラスのnewメソッド
Range.new( 最初の値, 最後の値 )
Rangeクラスのnewメソッドの使用例
range1 = Range.new (1, 10) # 1から10までの範囲を持つ範囲オブジェクトrange1を作成 range2 = Range.new ('a', 'j') # 文字a1から文字jまでの範囲を持つ範囲オブジェクトrange2を作成
Rangeクラスの使い方
先ほど紹介したようにRangeクラスの範囲オブジェクトを利用することで範囲内の繰り返し処理や範囲内に含まれているかのチェックなど、オブジェクト指向言語のRubyらしいプログラムを記述できます。
次から代表的なRangeクラスの使い方を紹介します。
繰り返し処理で使う
繰り返し処理とは、ある条件まで何度も同じ処理を実施するプログラムですが、一般的には決まった数だけ繰り返すプログラムが使われます。例えばC言語がベースになったプログラム言語でよくfor構文が使われますが、for構文では繰り返す数を指定します。
しかしRubyの繰り返し処理では数を指定することはありません。配列に対して繰り返し処理を適用するなら、配列オブジェクトと配列クラスのメソッドを使います。同じようにある数まで繰り返し処理をRubyで作る場合に使うのが、範囲オブジェクトとRangeクラスのメソッドです。
Rangeクラスのeachメソッドによる繰り返し処理の使い方を次に紹介します。
Rangeクラスのeachメソッドの例
out = 0 (1..10).each { |x| out = out + x } p out
この例は、範囲オブジェクトの(1..10)に対してeachメソッドを適用した例です。ブロックの中で1から10までの数の合計を計算し、その数を表示します。
範囲内に含まれているかのチェック
Rangeクラスのinclude?メソッドまたはmenber?メソッドを利用することで、範囲オブジェクトに含まれているかをチェックできます。
例えばアルファベットの文字を含む範囲オブジェクトにある文字が含まれているかをチェックする場合、次の例を参照してください。
chk = ('a'..'z') if ( chk.include?(target) ) then p "OK" else p "NG" end
この例は変数targetに格納された文字が小文字のアルファベットなら”OK”を、そうでないなら”NG”を表示します。例えばtargetの文字がxなら”OK”ですが数字や大文字なら”NG”を表示することで、文字のチェックが可能な書き方です。
またchk.include?(target)の代わりにchk.member?(target)と書いても同じ意味です。
日付で範囲オブジェクトを使う方法
Rangeクラスでは日付の範囲を含む範囲オブジェクトも作れます。そして日付の範囲オブジェクトに対して先ほどのinclude?またはmenber?メソッドを利用することで、ある期間に含まれているかのチェックも可能です。
日付で範囲オブジェクトを使う例
require 'date' term = Range.new(Date.parse("2020-04-05"), Date.parse("2020-05-07")) if( trem.include?(Date.parse(target_day)) ) then p "OK" else p "NG" }
この例は”2020-04-05″から”2020-05-07″の期間に含まれているかをチェックする例です。例えばtarget_dayが”2020-04-29″なら”OK”を、”2020-05-29″なら”NG”を表示します。
for文に範囲オブジェクトを使う
C言語をベースにしたプログラム言語の多くで繰り返し処理にfor構文が使えますが、Rubyでもfor構文による繰り返し処理が使えます。ただし、Rubyのfor構文はC言語のfor構文と使い方が違っており、繰り返す数ではなく繰り返しの範囲としてオブジェクトを指定します。
for構文の範囲として範囲オブジェクトを指定できます。次にC言語の次のfor構文をRubyで書き換えるた例を紹介します。
C言語のfor構文の例
for( i=1; i<=10; i++) { ... }
上と同じfor構文をRubyで書き換えた例
for i in (1..10) do ... end
このように範囲オブジェクトを利用してfor文を使うことは可能ですが、Rubyではeachメソッドなど便利な幾つもあるので他の言語ほど使いません。より読み易いプログラムを心がけてください。
まとめ
これまで紹介したようにRangeクラスの範囲オブジェクトを利用することで、繰り返し処理やチェック処理などをRubyらしく短く読み易いプログラムとして記述できます。
今回紹介した例の他にも範囲オブジェクトはいろいろな用途でプログラムに活用できます。ぜひ活用してスキルアップを目指してください。