2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Ruby】繰り返し文のまとめ

Last updated at Posted at 2024-10-29

はじめに

こんにちは、絶賛Ruby勉強中のものです。
本日はRubyで出てくる繰り返し文について簡単にまとめようと思い記事にしました。
繰り返すという点では同じですが、それぞれ違う用途で使われることが多くわからなくなってしまうことがあると思うので初心者向けではありますが見ていきたいと思います

Rubyの繰り返し文

まずはRubyの繰り返し文とひとくくりにしていますが、制御構文とメソッドにその性質をもつものがあります。
制御構文はifとかuntilcaseなどのことを言います。なので本来は一緒に紹介するものではないのですが、繰り返すというグループで囲むと同じなのでまとめて紹介していきます。

  • times(メソッド)
  • for(制御構文)
  • while(制御構文)
  • until(制御構文)
  • each(メソッド)
  • loop(メソッド)

times

timesは「○回繰り返す」と決まっている場合に便利な構文です。
例えば、5.timesとすると5回だけ処理を繰り返します。

times1.rb
5.times do |i|
  puts i
end
# 0
# 1
# 2
# 3
# 4

また、do ... endの代わりに中括弧 { ... }を使って以下のように短く記述することも可能です。

times2.rb
5.times { |i| puts i }

for

ruby以外のほかの言語の繰り返しといえばforを連想しますよね。
forは配列や範囲のすべての要素に対して繰り返し処理をしたいときに使用されます。

for1.rb
sum = 0
for i in 1..3
  sum += i
end
puts sum
# 6

Rubyのfor文は、すべての要素を繰り返し処理する時に便利ですが、Rubyでは一般的にeachの方がよく使われます。
理由の一つは、forはループの外でも変数が参照できてしまうためです。

scope.rb
# forの場合
for i in (1..3)
  puts i
end
puts i  # forではループ外でも変数iが使える

# eachの場合
(1..3).each do |j|
  puts j
end
puts j  # eachではエラーが出る

eachはブロックを使用しており、スコープが限定されるため、ループ外で変数が参照できません。
このことで思わぬ副作用を防ぎ、コードの安全性が向上します。

while

条件が真である限り繰り返しを行いたい場合に使用されます。

while1.rb
total = 0
i = 1
while i <= 5
  total += i
  i += 1
end
puts total
# 15

上記のように5回繰り返す場合、fortimesでも同じ結果を得られますが、条件を自由に設定できる点がwhileの特徴です。
例えば、以下のように合計が50に達するまで処理を繰り返す場合などはwhileが適しています。

while2.rb
total = 0
i = 1
while total < 50
  total += i
  i += 1
end
puts total

whileの追記

コメントで教えていただいたのですが、実はwhileはあまり出番がないようです!
教材ベースで学んでおいてこういった気づきがあるのも面白いですね。
では具体的にどういうことが説明してきます。while2.rbのコードについてみていきましょう

step.rb
total = 0
1.step do
  total += _1
  break if total >= 50
end
puts total

行数では 1 行しか減っていませんが,「i の値を初期化する」「i の値を 1 ずつ増やす」という処理をいちいち書かなてくよいぶん,把握しやすいように思います。
(Numeric#step は初期値に増分と上限・下限を与えて繰り返すイテレーターです。ここでは増分〔既定値 1〕を略し,上限を無しとして使っています)

上記のようにコメントをいただきました。
stepというメソッドは初めて知ったのですが、whileよりも冗長すぎなくて見やすいコードになりますね。
そう考えるとwhileの出番ってほんとに少ないのかもしれません。

until

条件が「偽」になるまで繰り返したい場合に使用します。
ifにもunlessという条件が偽の場合に処理を行う条件式がありましたが、untilwhileの逆バージョンと思っていただければ大丈夫です

unless.rb
total = 0
i = 1
unless total >= 50
  total += i
  i += 1
end
puts total

これはwhile2.rbunlessに書き直したコードです。whileとは条件式が逆になっています

each

Rubyではforの代わりに、配列や範囲オブジェクトに対する繰り返し処理にはeachが多く使用されます。
forに比べてスコープが狭くなり、思わぬ副作用を防ぐことができるためです。

each1.rb
sum = 0
(1..3).each do |i|
  sum += 1
end
puts sum

loop(追記)

こちらもコメントいただいたので追記です。
loopは無限ループ作るときくらいしか使わないと習ったのですが、whileの代わりに使う場面があるようです。

繰り返し処理の典型的なパターンの一つに以下のようなものがあります。

  • 処理 A を行う
  • その結果次第でループを抜ける
  • 抜けなかった場合は処理 B を行う
  • 以上を繰り返す
    ここで,処理 A が非常に単純なとき,while で書けます:
short_while.rb
while [処理 A とその結果による条件式]
  処理 B
end

しかし,[処理 A とその結果による条件式] が単純な式で書けない場合,非常に見づらいコードになります。
こういうときは loop メソッドを使って

loop.rb
loop do
  処理 A
  break if 条件式
  処理 B
end

と書くのがよい場合があります。

loopは無限ループのみしか使わない、いわばのけものと扱わずにこんなにスマートな使い方があることを教えていただきました。
他にもloopの使い方を知っている方は教えていただけると励みになります。

まとめ

Rubyの繰り返し文には、それぞれ独自の特徴と適した場面があります。

  • 固定回数の繰り返しには times
  • 配列や範囲オブジェクトの要素に対して繰り返しを行うには each
  • 自由な条件に基づく繰り返しが必要なら whileuntil。ただし、whileeachloopにとってかわられることが多く使う機会がない
  • スコープを意識せず使いやすいが、制御が必要な場合は forよりもeachが推奨されます
2
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?