Deep Insider の Tutor コーナー
>>  Deep Insider は本サイトからスピンオフした姉妹サイトです。よろしく! 
Ruby TIPS

Ruby TIPS

for文 ― ちょっと便利な繰り返し処理の構文とは?(2)

2016年7月22日

Rubyに用意されている繰り返し処理の構文のうち、for文の基本的な使い方と配列と組み合わせた利用例を解説。範囲や配列を利用して一定の回数だけ繰り返して文を実行する方法や、配列全体を処理する方法を紹介する。

ローグ・インターナショナル 羽山 博
  • このエントリーをはてなブックマークに追加

 前回の「TIPS:while修飾子/until修飾子/while文/until文 ― ちょっと便利な繰り返し処理の構文とは?」で紹介したように、Rubyではwhile文/until文/while修飾子/until修飾子を使った繰り返し処理が記述できる。この他に、for文も使用できる。今回は、そのfor文の基本的な使い方を説明し、for文と相性のよい配列処理について見ていく。

for文の基本的な使い方

 for文は、範囲や配列やブロックなどに含まれる各オブジェクト要素を順に変数に代入し、を繰り返して実行する。代入する要素がなくなったら繰り返しを終了する。

【構文】for文を使った繰り返し処理

for 変数…… in範囲や配列やブロック [do]
  式……
end

範囲に対するfor文

 簡単な例で見てみよう。

sample008.rb
for i in 0..4
  puts i * 2
end
リスト2.1 for文の簡単な例(範囲を利用した繰り返し)

 inの後に書かれた0..40以上4以下の範囲を表す。したがって、変数i01234が順に代入され、式が順に繰り返し実行される。

 実行例は以下の通り。前回のリスト1.3と同様、10未満の偶数を表示する。

コンソール
$ ruby sample008.rb 
0
2
4
6
8
$ 
実行例2.1 10未満の偶数を表示するプログラムの実行例

プログラムを実行すると、変数iの値が表示される。動作を確認するためだけなので、何の変哲もない結果だが、変数iの値が10未満である間は繰り返されていることがわかる。

 範囲を表すオブジェクトはa..bのように..で区切ると「a以上b以下」という意味になり、a...bのように...で区切ると「a以上b未満」という意味になる。for文は前判断型なので、inの後にオブジェクトが1つもない場合には繰り返し処理の中身は実行されない。

配列に対するfor文

 また、inの後には、配列も指定できるので、リスト2.1の例は以下のようにも書ける。

sample009.rb
for i in [0,1,2,3,4]
  puts i * 2 
end
リスト2.2 for文の簡単な例(配列を利用した繰り返し)

inの後に書かれた配列の要素が変数iに順に代入され、式が順に繰り返し実行される。

ブロックを利用した繰り返し処理

 繰り返し処理を行うには、for文を使う方法以外にも、ブロックを利用する方法もある。例えば、リスト2.3やリスト2.4のように書いても上で見た例と同じことができる。ブロックについての詳細は、次回以降のTIPSで説明するので、今回はコードを掲載するにとどめたい。

sample010.rb
5.times do |i|
  puts i * 2
end
リスト2.3 ブロックを利用して繰り返し処理を行う例(Integerクラスを使う)

Integerクラスのtimesメソッドを使えば、ブロックパラメーター(=||で囲まれた中にある変数)に0からtimes-1までの整数が順に渡される。つまりiには0から4までが順に渡されることになる。

sample011.rb
a = [0, 1, 2, 3, 4]
a.each do |i|
  puts i * 2
end
リスト2.4 ブロックを利用して繰り返し処理を行う例(配列を使う)

Arrayクラスのeachメソッドを使えば、ブロックパラメーター(=||で囲まれた中にある変数)に配列の各要素が順に渡される。つまりiには0から4までが順に渡されることになる。

 これらについても、実行例は前掲の実行例2.1と同じなので省略する。

for文と配列

 for文による繰り返し処理は、範囲を使って変数の値を順に変えていくことができるので、配列の処理ととても相性がいい(配列の基本については「TIPS:関数で複数の返り値を返す/関数の引数は値渡し ― コーディングミスを防ぐには?(2)」を参照してもらいたい)。

配列

 例えば、すごろくのようなゲームで、マス目を配列で表すものとする。特に何もないマスには0という値を入れ、1つ進むマスに1を入れておくのであれば、以下のようなコードを書けばよい。

sample012.rb
limit = 10  # マス目は10個
cells = Array.new(limit)

# すべて0にする
for i in 0..limit-1
  cells[i] = 0
end

# セルをランダムに選んで1を入れる
r = Random.new()
cells[r.rand(10)] = 1

# 配列の内容を表示してみる
p cells
リスト2.5 for文を使って配列の要素を全て処理する

配列cellsの要素数はlimitで表されており、ここでは10を指定している。for文では、0からlimit-1までをiに代入しながら処理を繰り返す。実行する処理は単に配列のi番目の要素に0を代入するだけ。続いてランダムに選択したセルに1を入れる。

 実は、全ての要素を0にするには、繰り返し処理を使わなくてもcells.fill(0)だけでも構わない。ここでは、繰り返し処理の書き方を知るためにあえてfor文を使った。実行結果は以下のようになる。1が表示される位置はランダムに決まる。

コンソール
$ ruby sample012.rb
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
実行例2.2 for文を使った配列の処理の結果を確認する

pメソッドを使って配列の要素を全て表示してみた。繰り返し処理によって全ての要素に0を代入した後、ランダムな位置の要素に1を代入したことが分かる。

二次元配列

 2次元の配列の要素を全て処理したい場合には、for文を二重にネストすればよい(=入れ子にする)。以下の例は単に2次元の配列を作り、その要素に「nn列」という文字列を代入するだけのプログラムである。

sample013.rb
# 2次元の配列を作る
def make2d(x,y)
  a = Array.new(x)
  for i in 0..x-1
    a[i] = Array.new(y)
  end
  return a
end

# 2次元の配列の全ての要素に値を代入する
a = make2d(3, 4)
for row in 0..2
  for col in 0..3
    a[row][col] = row.to_s + "行" + col.to_s + "列";
  end
end

# 配列の対角要素の値だけを表示する
for i,j in [[0,0],[1,1],[2,2]]
  puts a[i][j]
end
リスト2.6 for文を使って二次元の配列を処理する

最初に2次元の配列を作るためのmake2d関数を定義してある。その関数を使って2次元の配列を作成し、変数aでその配列を参照できるようにする。続いて、for文を二重にして配列aの各要素に値を代入する。最後に、配列の対角要素だけを表示している。

 このプログラムのポイントは2つ。

 まず、2次元の配列を二重のfor文で処理するところだが、row0から2まで、col0から3まで以下の図のように変化する。内側のfor文に描かれている変数colが先に動くことに注意しよう。

2重のfor文
図2.1 for文を二重にネストさせた時の変数の値の変化

colが内側のfor文で使われる変数で、rowが外側のfor文で使われる変数。

 もう1つのポイントは、最後のfor文。このように、複数の変数に一度に値を代入しながら繰り返しができる。最初に、i,j[0,0]がそれぞれ代入され、putsが実行される。次に[1,1]がそれぞれ代入されてputsが実行され、最後に[2,2]がそれぞれ代入されてputsが実行される。for文のネストとは異なるが、複数の変数の値を簡潔な書き方でまとめて変えられる便利な機能だ。最後に実行例を示しておこう。

コンソール
$ ruby sample013.rb
0行0列
1行1列
2行2列
実行例2.3 二重のfor文の動作を確認する

作成した配列は正方行列ではないが、行番号と列番号が同じ要素を表示してみた。for文をネストさせた場合や、複数の変数に値を代入しながら繰り返し処理を実行させた場合の結果が確認できる。

まとめ

 Rubyでは、while文/until文/while修飾子/until修飾子を使った繰り返し処理ができるほか、各種プログラミング言語でも一般的なfor文を使った記述方法もサポートされている。そのfor文では、範囲や配列などのオブジェクトの要素を順に変数に代入しながら繰り返し処理が書ける。

処理対象:for文 カテゴリ:文法 > 制御構造 > 繰り返し

※以下では、本稿の前後を合わせて5回分(第8回~第12回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

Ruby TIPS
8. if修飾子/unless文/case文 ― ちょっと便利な条件分岐の構文とは?

Rubyには、if文のような一般的なもの以外にも、if修飾子/unless文/unless修飾子/case文といった便利な条件分岐の構文が用意されている。その基本的な使い方を解説。

Ruby TIPS
9. while修飾子/until修飾子/while文/until文 ― ちょっと便利な繰り返し処理の構文とは?(1)

Rubyに用意されている繰り返し処理構文のうち、while文/until文の基本的な使い方と落とし穴を解説。また、while/until「修飾子」を使った簡潔な記述方法にも言及する。

Ruby TIPS
10. 【現在、表示中】≫ for文 ― ちょっと便利な繰り返し処理の構文とは?(2)

Rubyに用意されている繰り返し処理の構文のうち、for文の基本的な使い方と配列と組み合わせた利用例を解説。範囲や配列を利用して一定の回数だけ繰り返して文を実行する方法や、配列全体を処理する方法を紹介する。

Ruby TIPS
11. ブロック ― ちょっと便利な繰り返し処理の構文とは?(3)

Rubyに用意されている繰り返し処理の構文のうち「ブロック」を使えば、繰り返し処理をより簡潔に書ける。その基本的な使い方と、自作メソッドでの利用例を解説する。

Ruby TIPS
12. クラスとそのコンストラクター/アクセサー/メソッドを定義し利用するには?

Rubyプログラミングの基本中の基本として、クラスの定義から、そのインスタンスの作成・利用、インスタンスメソッドの定義、変数へのアクセスまでを説明する。

サイトからのお知らせ

Twitterでつぶやこう!