Ruby for ループとイテレーション
for ループをユースすることで、シーケンス内の各エレメントに対してコードブロックをリピートしてエグゼキュート(実行)することが可能になります。
本章では、これまでのコントロールフローに対する理解をベースに、Ruby における for ループの包括的なガイドを提供し、よりアドバンスドなループ・テクニックを学習するための準備を行います。
1. for ループの基礎知識を理解する
Ruby における for ループは、アレイ (Arrays) や レンジ (Ranges) などのアイテム・コレクションをトラバース(走査)するためのコンサイス(簡潔)なアプローチを提供します。そのベーシックなシンタックスは以下の通りです:
for variable in collection do
# コレクション内の各アイテムに対してエグゼキュートするコード
end各パートをブレイクダウンしてみましょう:
- for:ループをスタートさせるためのキーワードです。
- variable(バリアブル):コレクション内のカレント(現在)のアイテムの値を、各イテレーションのプロセスでホールドするバリアブルです。
- in:このキーワードは、ループが後続のコレクションのエレメントをトラバースすることを指定します。
- collection(コレクション):トラバースしたいアレイ、レンジ、またはその他のエンニュメラブル(Enumerable)オブジェクトです。
- do:各アイテムに対してエグゼキュートされるコードブロックの開始をマークするキーワードです。これはオプショナル(任意)であり、省略してニューライン(改行)で代替することも可能です。
- # エグゼキュートするコード:コレクション内の各アイテムに対してエグゼキュートされるコードブロックです。
- end:ループの終了をマークするキーワードです。
以下は、ナンバーのアレイをトラバースするシンプルなサンプルです:
numbers = [1, 2, 3, 4, 5]
for number in numbers do
puts number * 2
end
# アウトプット:
# 2
# 4
# 6
# 8
# 10このサンプルでは、for ループが numbers アレイをトラバースします。各イテレーションにおいて、number バリアブルがアレイ内のカレント・エレメントの値を取得し、do...end ブロック内のコードをエグゼキュートして、そのナンバーに2を乗算したリザルトをプリント(出力)します。
2. レンジ (Range) のトラバース
for ループは、ナンバーのレンジをトラバースするためにもユースできます。レンジとは、スタート値とエンド値によってディファイン(定義)されるナンバーのシーケンスです。
for i in 1..5 do
puts "イテレーション回数: #{i}"
end
# アウトプット:
# イテレーション回数: 1
# イテレーション回数: 2
# イテレーション回数: 3
# イテレーション回数: 4
# イテレーション回数: 5このサンプルでは、for ループが 1..5 のレンジをトラバースします。このレンジには 1、2、3、4、および 5 のナンバーが含まれます。各イテレーションの間に、バリアブル i はレンジ内の各ナンバーを取得します。#{i} というシンタックスはストリング・インターポレーションと呼ばれ、ストリング内にバリアブルの値をエンベデッド(埋め込み)することを許可します。(これについてはデータ型とバリアブルのモジュールでカバーされています)。
1...5 をユースして、エンド値を含まないレンジ(エクスクルーシブ・レンジ)をクリエイトすることもできます。これは最後のエレメントをエクスクルード(除外)します。
for i in 1...5 do
puts "イテレーション回数: #{i}"
end
# アウトプット:
# イテレーション回数: 1
# イテレーション回数: 2
# イテレーション回数: 3
# イテレーション回数: 43. do の省略とインライン・シンタックス
前述の通り、do キーワードはオプショナルです。これを省略し、直接ニューラインをユースすることができます:
numbers = [1, 2, 3, 4, 5]
for number in numbers
puts number * 2
endさらに、ループのボディがシングルステートメントしか含まない場合、極めてコンパクトなインライン・シンタックスをユースできます:
numbers = [1, 2, 3, 4, 5]
for number in numbers do puts number * 2 endこの記述はよりコンパクトですが、特に複雑なループのボディにおいてはリーダビリティ(可読性)が低下する傾向があるため、アビュース(乱用)は推奨されません。
4. ストリングにおける for ループのユース
for ループは、ストリング内の各キャラクターをトラバースするためにもユースできます。ただし、Ruby はストリングのオペレーションにおいてより便利なメソッドを提供しているため、このアプローチは一般的ではありません。以下は1つのサンプルです:
word = "hello"
for char in word.chars do
puts char.upcase
end
# アウトプット:
# H
# E
# L
# L
# Oこのサンプルでは、word.chars が "hello" というストリングをキャラクターのアレイ ['h', 'e', 'l', 'l', 'o'] にコンバートしています。その後、for ループがこのアレイをトラバースし、char.upcase が各キャラクターをアッパーケース(大文字)にコンバートしてプリントします。
5. ネストされた for ループ
1つの for ループを別の for ループの内部に配置(ネスト)することで、マルチプルなコレクションをトラバースしたり、より複雑なパターンをクリエイトしたりすることができます。以下は、マルチプリケーション・テーブル(九九の表)をプリントするネストされた for ループのサンプルです:
for i in 1..3 do
for j in 1..3 do
puts "#{i} * #{j} = #{i * j}"
end
end
# アウトプット:
# 1 * 1 = 1
# 1 * 2 = 2
# 1 * 3 = 3
# 2 * 1 = 2
# 2 * 2 = 4
# 2 * 3 = 6
# 3 * 1 = 3
# 3 * 2 = 6
# 3 * 3 = 9このサンプルでは、アウター(外側)の for ループが 1 から 3 までのナンバーをトラバースし、インナー(内側)の for ループも 1 から 3 までのナンバーをトラバースします。i と j の各コンビネーションに対して、インナーループ内のコードがエグゼキュートされ、乗算のリザルトがプリントされます。
6. for ループと他のイテレーション・メソッドの比較
for ループは Ruby における有効なイテレーション・アプローチの1つですが、一般的には他のメソッド(each、map、select、reject など)と比較して「Ruby らしい(Ruby-like/Idiomatic)」とは見なされません。後続のモジュールで紹介されるこれらのメソッドは、よりコンサイスでエクスプレッシブ(表現豊か)であるため、通常はこちらが好まれます。とはいえ、イテレーションの基礎をマスターし、初期の Ruby コードをリーディングするためには、for ループの理解が依然として非常に重要です。
以下は、前述のマルチプリケーション・テーブルのサンプルを、each メソッド(後の章で詳細に解説します)をユースしてリライトしたものです:
(1..3).each do |i|
(1..3).each do |j|
puts "#{i} * #{j} = #{i * j}"
end
endこのコードは、ネストされた for ループのサンプルと完全に同一のリザルトを実現しますが、Ruby デベロッパーの視点からはよりリーダビリティが高く、Ruby のイディオムにも合致しています。
7. for ループ内での break と next のユース
break および next キーワードをユースして、for ループ内部のエグゼキュート・フローをコントロールすることができます。これら2つのキーワードは前の章ですでにイントロダクションされています。
- break:このキーワードは、即座にループ全体をエグジット(脱出)します。
- next:このキーワードは、カレントのイテレーションをスキップし、コレクション内の次のアイテムへと直接スキップします。
以下は、break をユースしたデモンストレーションのサンプルです:
numbers = [1, 2, 3, 4, 5]
for number in numbers do
if number > 3
break
end
puts number
end
# アウトプット:
# 1
# 2
# 3このサンプルでは、ループが numbers アレイをトラバースします。number が 3 を超えた時点で break ステートメントがトリガーされ、ループは即座にターミネート(終了)します。
以下は、next をユースしたデモンストレーションのサンプルです:
numbers = [1, 2, 3, 4, 5]
for number in numbers do
if number % 2 == 0
next
end
puts number
end
# アウトプット:
# 1
# 3
# 5このサンプルでは、ループが numbers アレイをトラバースします。number が偶数である(つまり、2 で除算した剰余が 0 である)場合、next ステートメントがトリガーされ、カレントのイテレーションがスキップされます。リザルトとして、奇数のみがプリントされます。