Ruby

【Ruby】列挙するメソッド

メソッド

数を順に列挙していくインスタンスメソッドたちです。繰り返しをするメソッドのことをイテレータと言います。分かりやすくする為に、回数がそのまま見える処理しか書いていません。それと、自分が使い方を知ってるメソッドしか書いてないので、調べてみると他にもたくさんあります。

Integer#times

お馴染みの times メソッドです。レシーバの回数だけ繰り返します。

3.times do
  p "Ruby"
end
"Ruby" # 0
"Ruby" # 1
"Ruby" # 2
=> 3

ただし、上記のようにこのメソッドは 0 回から始まることに注意してください。試してみたところ、Range を使っても制御できないようです。ブロックパラメータを渡すとその様子が分かりやすいです。

3..6.times do |n|
  p n
end
0
1
2
3
4
5
=> 3..6

Integer#upto

レシーバから始まり、その後はレシーバからひとつずつ加算しながら、引数として与えられた 回数 上限まで繰り返します。 (もしレシーバの方が引数より大きい場合は繰り返せません。)

10.upto(20) do |n|
  p n
end
10
11
12
13
14
15
16
17
18
19
20
=> 10

ブロックパラメータがない場合は、パラメータを使用しないだけの処理です。

5.upto(10) do
  p "Ruby"
end
"Ruby" # 5
"Ruby" # 6
"Ruby" # 7
"Ruby" # 8
"Ruby" # 9
"Ruby" # 10
=> 5

@scivola さんがコメントで教えてくれたことですが、浮動小数点数は無視されるようです。整数しか扱わない Integer のメソッドというだけあるということでしょうか。

0.upto(Math::PI) do |n|
  p n
end
0
1
2
3
=> 0

Integer#downto

レシーバから始まり、その後はレシーバからひとつずつ減算しながら、引数として与えられた 回数 下限まで繰り返します。 (もしレシーバの方が引数より小さい場合は繰り返せません。)

5.downto(0) do |n|
  p n
end
5
4
3
2
1
0
=> 5

ブロックパラメータがない場合は、パラメータを使用しないだけの処理です。

10.downto(5) do
  P "Ruby"
end
"Ruby" # 10
"Ruby" # 9
"Ruby" # 8
"Ruby" # 7
"Ruby" # 6
"Ruby" # 5
=> 10

浮動小数点数については upto と同じのようです。

7.downto(Math::PI) do |n|
  p n
end
7
6
5
4
=> 7

Numeric#step

こちらはレシーバから始まって第一引数(上限/下限)を超えないように第二引数を加算及び減算しながら繰り返します。 (もし第二引数が正の数の場合、レシーバが第一引数(上限)より大きいと繰り返せません。反対に、もし第二引数が負の数の場合、レシーバが第一引数(下限)より小さいと繰り返せません。)

5.step(10, 2) do |n|
  p n
End
5
7
9
=> 5
0.step(6, 2) do
  p "Ruby"
end
"Ruby" # 0
"Ruby" # 2
"Ruby" # 4
"Ruby" # 6
=> 0

Array#each

配列の要素を順に取り出す定番のメソッドです。ブロックパラメータにそれぞれの要素をインデックス順で渡します。

ary = %w(Ruby Python PHP Java)
ary.each do |word|
  p word
end
"Ruby"
"Python"
"PHP"
"Java"

Range#each

範囲内のオブジェクトをブロックパラメータへ順番に渡していき、それぞれを処理します。

(0..-5).each do |n|
  p n
end
-5
-4
-3
-2
-1
0
=> -5..0

おしまい

自分はここにあげたメソッドについて、これくらいしか知りませんが、ここには書いてない注意事項や面白い話などありましたら、どうぞコメントください。 each の強化版のように each が付くメソッドは他にもありますが、それらは Enumerable モジュールのメソッドとして用意されているみたいです。

これらのメソッドを調べているうちに、ブロックが渡されなかった場合は Enumerator オブジェクトを返すという言葉を目にしましたが、Enumerator がどんなクラスなのかまだ分からないので書きませんでした。