範囲オブジェクトを繰り返し処理の中で利用する

範囲オブジェクトは指定した最初の値と最後の値の範囲を表すオブジェクトです。範囲オブジェクトは繰り返し処理と一緒に使用して順に値を取得したり、ある値が範囲内に含まれているかどうかを調べるために使われます。ここでは Ruby における範囲オブジェクトについて、特に繰り返し処理を一緒に使用する場合に限定して解説します。

(2021 年 06 月 30 日公開 / 2022 年 10 月 17 日更新)

範囲オブジェクトの作成と使い方

範囲オブジェクトを作成するには .. 演算子を使用します。

first..last

.. 演算子の左辺に最初の値を指定し右辺に最後の値を指定します。最初と最後の値には数値や文字列などのオブジェクトが指定できます。

具体的には次のように使用します。

range1 = 5..10
range2 = "d".."g"

変数「range1」には 5 から 10 の範囲を持つ範囲オブジェクトが代入されます。また変数「range2」には "d" から "g" の範囲を持つ範囲オブジェクトが代入されます。

最初と最後の値には任意のオブジェクトが指定できますが、最初と最後の値は大きいか小さいか等しいかなどの比較が出来るものでなければなりません。数値と数値、文字列と文字列などが一般的には利用されることが多いです。

なおよく似た演算子として ... 演算子が用意されています。

first...last

この場合、範囲オブジェクトが持つ範囲に最後の値は含まれません。

Rangeクラスを使って範囲オブジェクトを作成する

範囲オブジェクトは実際には Range クラスのオブジェクトです。 .. 演算子や ... 演算子によって範囲オブジェクトを作成できますが、 Range クラスのクラスメソッドである new メソッドでも作成できます。

Range.new(first,last[, exclude_end])

引数の「first」には最初の値を、「last」には最後の値を指定します。また「exclude_end」は最後の値を要素として含めるかどうかを指定します。真の値を指定した場合は最後の値を含めません。省略された場合は最後の値を含めます。

具体的には次のように使用します。

range1 = Range.new(5, 10)
range2 = Range.new(5, 10, true)

作成される範囲オブジェクトは .. 演算子と ... 演算子を使用した場合と同じです。

範囲オブジェクトを繰り返し処理で使用する場合の注意点

範囲オブジェクトを for 文の中で使用した場合、最初の値から最後の値まで( .. 演算子を使って作成した場合)順に値を取り出し要素として返します。最初の値の次の値としてどのような値を取り出すのかは、最初と最後に指定したオブジェクトの元になっているクラスで定義されている succ メソッドを使われます。

for 文の基本的な使い方については「for文を使った繰り返し処理」を参照されてください。

succ メソッドがどのような値を返すのかはクラスによって異なります。例えば整数を扱う Integer クラスの succ メソッドの場合、 succ メソッドは次の整数を返します。

1.succ  ->  2
2.succ  ->  3
3.succ  ->  4

よって最初に指定した数値から最後に指定した数値まで順に次の整数を要素として返します。

実際には次のように使います。

for num in 3..5 do
  puts(num)
end

上記の場合は 3, 4, 5 と順に出力されます。

また文字列を扱う String クラスの succ メソッドの場合、 succ メソッドは次の文字列を返します。具体的には文字列の一番右端の文字がアルファベットなら、次のアルファベット(例えば "ca" だったら "cb")を返し、一番右端の文字が数値だった場合は 1 を加算した文字(例えば "73" だったら "74" )が返されます。

また繰り上げも行われます。文字列が "fcz" だったら次の文字列は "fda" となります。(一番右端の文字が "z" の次の "a" になり、右から 2 番目の文字が "c" から "d" になります)。文字列が "139" だったら次の文字列は "140" となります。

"a".succ  ->  "b"
"z".succ  ->  "aa"
"Ad".succ ->  "Ae"
"Az".succ ->  "Ba"
"zz".succ ->  "aaa"
"4".succ  ->  "5"
"9".succ  ->  "10"
"a9".succ ->  "b0"
"9z".succ ->  "10a"

文字列にアルファベットや数値が含まれる時にその他の文字も含まれる場合はその他の文字はそのまま変わりません。数値の場合の符号も無視されます。

"4:5:9".succ  ->  "4:6:0"
"-5".succ     ->  "-6"

実際には次のように使います。

for s in "a".."d" do
  puts(s)
end

上記の場合は "a", "b", "c", "d" と順に出力されます。

このように繰り返し処理の中で範囲オブジェクトを使用する場合は、次の値として succ メソッドを使用するため succメソッドが定義されていないクラスのオブジェクトは最初と最後の値として指定できません。(範囲オブジェクトとしては作成出来ますが、「for」文などに使うとエラーとなります)。浮動小数点数を表す Float クラスでは succ メソッドが定義されていませんので浮動小数点数で指定された範囲オブジェクトは繰り返し処理の中で指定できません。

また最初の値が最後の値よりも大きい範囲オブジェクトも作成できますが、 for 文の中で指定しても要素を 1 つも返しません(最初の値も返しません)。

サンプルコード

では簡単なプログラムで確認してみます。

# encoding: UTF-8

for num in 18..20 do
  puts("num = " + num.to_s)
end

puts();

for str in "Ax".."Bb" do
  puts("str = " + str)
end

下記のように実行して下さい。

範囲オブジェクト

-- --

Ruby における範囲オブジェクトについて、特に繰り返し処理を一緒に使用する場合に限定して解説しました。

( Written by Tatsuo Ikura )

広告
Profile
profile_img

著者 / TATSUO IKURA

プログラミングや開発環境構築の解説サイトを運営しています。