【Ruby Silver】Rubyのループ処理まとめ

## 自己紹介
はじめまして、はる（[@lemonade_37](https://twitter.com/lemonade_37)）と申します。完全異業種からのエンジニア転職を目指して学習をしています。
　
## 概要
Ruby Silver3.1 の学習のために使用した、Rubyのループ処理のまとめです。
既にわかりやすくまとめられている記事も多いですが、Ruby Silverの問題を解きながら学んだ、引っかかりやすい部分なども含めてまとめています。

:::note warn
初学者のため、間違っている箇所や、紹介した方法よりも良い方法があるかもしれませんので、その際は教えて頂けると嬉しいです🙇
:::


## ループ処理の基礎
ループ処理の概念や基礎についてはこちらの記事でまとめました。

https://qiita.com/lemonade_37/items/0660f9ee6ca2dc09d42d

## 配列やハッシュ内で繰り返す系
- `for`：指定した配列の要素に順番に実行したり、指定した範囲分繰り返しを行う。
※`do`省略可
※[`for`と`each`の違いについては別記事にいただいたコメントが大変わかりやすいためご参照下さい](https://qiita.com/lemonade_37/items/0660f9ee6ca2dc09d42d#comment-dac8b0a71beb9bf41877)
    ```ruby
    for i in [1, 2, 3] do
      print i * 2
    end
    #=> 246
    
    for i in 1..5 do
      print i
    end
    #=> 12345
    ```
　　
- `each`：配列の各要素に対してブロックを評価する。ハッシュにも使用できる。
※ブロックを渡した時は`do`がない
    ```ruby
    [1, 2, 3].each do |i|
      print i
    end
    #=> 123
    
    {a: 1, b: 2}.each {|a| print a}
    #=> [:a, 1][:b, 2]
    ```
    :::note info
    `each`の仲間
    - `reverse_each`：各要素に対し**逆順**でブロックを評価する。
    ```ruby
    [1, 2, 3].reverse_each do |i|
      print i
    end
    #=> 321
    ```
    - `each_index`：配列の各要素の**インデックス**に対してブロックを実行する。
    ```ruby
    ["a", "b", "c"].each_index {|i| print i}
    #=> 012
    ```
    - `each_with_index`：配列の**各要素**と、**各要素のインデックス**を一緒にブロックを渡せる。
    ```ruby
    ["a", "b", "c"].each_with_index {|n, i| puts "値：#{n} インデックス：#{i}"}
    =begin
    =>出力
      値：a インデックス：0
      値：b インデックス：1
      値：c インデックス：2
    =end
    ```
    

## ループ終了の条件を指定する系

- `while`：指定した条件式が**真である間**（偽になるまで）ループする。
※`do`省略可
    ```ruby
    ary = [1, 2, 3, 4, 5, 6, 7]
    i = 0
    while i < 5 do
      print ary[i]
      i += 1
    end
    #=> 12345
    ```
　　
- `until`・`while not`：指定した条件式が**偽である間**（真になるまで）ループする。`while`の逆。
※`do`省略可
　　
- `loop`：**`break`でループを終了させない限り**ループし続ける。
    ```ruby
    a = 0
    loop do
      print a
      a += 1
      if a >= 7
        break
       end
    end
    #=> 0123456
    ```


## ループ回数を指定する系

- `times`：指定した回数だけ繰り返す。指定が**正の整数**でない場合は**何もしない**。
    ```ruby
    3.times {print "Hello"}
    #=> HelloHelloHello
    ```
    :::note warn
    `times`のループの1回目は**0番からスタート**するため、出力は下記のようになる。
    ```ruby
    3.times do |i|
      print i
    end
    #=> 012
    ```
　　
- `upto`：**指定した数値**から**MAXの数値**まで1ずつ増やしながら繰り返す。指定は整数（負の数もOK）で行う。
    ```ruby
    5.upto(10) {|i| print i}
    #=> 5678910
    ```
    :::note warn
    `1`という数値からスタートし、`3`という数値までループするため、**スタートの数値は`1`**。
    `times`と混同しないよう注意！
    ```ruby
    1.upto(3) do |i|
      print i
    end
    #=> 123
    ```
　　
- `downto`：**指定した数値**から**MINの数値**まで1ずつ減らしながら繰り返す。指定は整数（負の数もOK）で行う。
    ```ruby
    0.downto(-5) {|i| print i}
    #=> 0-1-2-3-4-5
    
    3.downto(1) do |i|
      print i
    end
    #=> 321
    ```
　　
- `step`：**指定した数値**から**指定した上限・下限**まで**指定した数ずつ**増やし / 減らしながら繰り返す。
上下限に負の数が指定された場合は、下限として解釈される。
スタートの指定値には**少数や負の数**も指定できる。（`upto`と`downto`の自由度高いバージョンっぽい）
例）`4.5`からスタートし、`1.5`ずつ増やしながら、`7.5`まで繰り返す。
    ```ruby
    4.5.step(7.5, 1.5) {|n| print n}
    #=> 4.56.07.5
    ```
    :::note info
    - 各ステップの大きさを指定しなければ、1回の繰り返しの増減幅はデフォルトで`1`になる。
        ```ruby
        2.step(5) {|n| print n}
        #=> 2345
        ```
    - 整数と少数を混ぜてもエラーにはならない。どちらか片方でも少数のときは、**出力が少数で表示される**。
        ```ruby
        2.0.step(5) {|n| print n}
        #=> 2.03.04.05.0
        ```

## その他
- `next`：`next`を使った時点でそれ以降の処理を飛ばして次のループに移る。
例）`2`の時は`next`以降の`print a`が飛ばされて、`2`だけ出力されない。
    ```ruby
    [1,2,3,4].each do |a|
      next if a == 2
      print a
    end
    #=> 134
    ```
　　
- `redo`：`redo`を使うとループの初めから処理を繰り返す。
:::note info
`redo`するかどうかは、`each do |a|`の部分の`a`の値で判断している。`redo`の繰り返しは**1回のみ**行われる。
例文では、`each do |2|`のときの処理が2回繰り返されている。each文の中で`a += 1`で`a`の値は`3`になっているので、`3`が2回出力されている。
```ruby
[1,2,3,4].each do |a|
  a += 1
  print a
  redo if a == 2
end
#=> 23345
```
:::
　　
- `break`：`break`を使った時点でループを抜け出すことができる。
 
## まとめ
苦手意識のあったループ処理ですが、ひとつひとつ整理して、実際にコードを動かしてみることで少し理解できました。
Ruby Silverをきっかけに勉強できてよかったです！

　
## 参考記事
- [Ruby　ループ処理をまとめてみた](https://qiita.com/zuttti25/items/168897e69696d38b8c50)
- [ruby 繰り返し処理 基本操作まとめ](https://qiita.com/may88seiji/items/1995cd03414fc51b7246)