基礎

Rubyのfor文入門|配列や範囲を使った繰り返し処理

for文はコレクション(配列や範囲)の各要素に対して順番に処理を行う繰り返し構文です。Rubyではeachメソッドの方がよく使われますが、for文は他の言語から来た方にも馴染みやすい構文です。この記事ではfor文の基本から、eachとの違いまで解説します。

基本的な使い方

範囲(Range)を使ったfor文

for文はfor 変数 in コレクションの形式で記述します。

Ruby
for i in 1..5
  puts "#{i}回目の繰り返し"
end
実行結果
1回目の繰り返し
2回目の繰り返し
3回目の繰り返し
4回目の繰り返し
5回目の繰り返し

1..5は1から5までの範囲オブジェクトで、for文は各要素を順番に変数iに代入して処理を実行します。1...5(ドット3つ)にすると末尾を含まない1から4までの範囲になります。

配列を使ったfor文

Ruby
fruits = ['りんご', 'バナナ', 'みかん', 'ぶどう']

for fruit in fruits
  puts "果物: #{fruit}"
end
実行結果
果物: りんご
果物: バナナ
果物: みかん
果物: ぶどう

for文とeachの違い

for文とeachメソッドの最大の違いは変数のスコープです。

Ruby
# for文: ループ変数がブロック外でもアクセス可能
for i in 1..3
  x = i
end
puts "for文後のx: #{x}"  # アクセスできる

# each: ブロック変数はブロック外からアクセスできない
(1..3).each do |j|
  y = j
end
puts "each後のy: #{y}"  # yにはアクセスできる(ブロック外で定義されたため)
# puts j  # エラー!jはブロック内でのみ有効
実行結果
for文後のx: 3
each後のy: 3

for文のループ変数iはfor文の外でも有効です。一方、eachのブロック変数|j|はブロック内でのみ有効です。変数のスコープを限定できるeachの方がバグを防ぎやすいため、Rubyではeachが推奨されています。

実践的な使い方

九九の表

Ruby
for i in 1..5
  row = ''
  for j in 1..5
    row += "#{(i * j).to_s.rjust(3)}"
  end
  puts row
end
実行結果
  1  2  3  4  5
  2  4  6  8 10
  3  6  9 12 15
  4  8 12 16 20
  5 10 15 20 25

合計と平均の計算

Ruby
scores = [85, 92, 78, 95, 67, 88]
total = 0
max = scores[0]
min = scores[0]

for score in scores
  total += score
  max = score if score > max
  min = score if score < min
end

puts "成績: #{scores.inspect}"
puts "合計: #{total}"
puts "平均: #{(total.to_f / scores.length).round(1)}"
puts "最高点: #{max}"
puts "最低点: #{min}"
実行結果
成績: [85, 92, 78, 95, 67, 88]
合計: 505
平均: 84.2
最高点: 95
最低点: 67

ハッシュの配列を処理

Ruby
students = [
  {name: '田中', score: 85},
  {name: '佐藤', score: 92},
  {name: '鈴木', score: 78}
]

for student in students
  grade = student[:score] >= 80 ? '合格' : '再試'
  puts "#{student[:name]}: #{student[:score]}点(#{grade})"
end
実行結果
田中: 85点(合格)
佐藤: 92点(合格)
鈴木: 78点(再試)
Rubyではeachが主流

Rubyコミュニティではfor文よりもeachメソッドが広く使われています。eachはブロック変数のスコープが限定されるため安全で、Rubyらしいイディオムです。for文は他の言語に慣れた方への橋渡しとして知っておくと便利です。

for文のスコープに注意

for文のループ変数はfor文の外でも参照できてしまいます。意図せず同名の変数を上書きするバグが起こりやすいため、特にこだわりがなければeachを使いましょう。

まとめ

  • for 変数 in コレクションで繰り返し処理を行う
  • 範囲(Range)や配列を対象にできる
  • for文のループ変数はブロック外でも有効(スコープが広い)
  • Rubyではeachメソッドの方が推奨されている
  • ネストしたfor文で二次元的な処理も可能