【目的別逆引き】eachだけじゃないぞ！RubyのEnumerable60メソッドを紹介

Rubyの魅力。

「シンプルにかける」「フレームワーク優秀すぎる」
とか色々ありますよね。

ただ、個人的にはループ処理用のメソッドの多さも魅力の一つだと思っています。

初めてRubyを学んだ時、

「え、こんなにループ処理用のメソッドあるん？大体なんでもできるやん？」

と思いました。


せっかくなので、色々なメソッドを使ってみるのも良いかもですね。

ただメソッドが多すぎて、

「こんな時はどのメソッド使ったら良いの？」

というのがわかりにくいという難点もあります。

そこでこの記事では、「[Ruby3.3公式リファレンスマニュアル：Enumerableモジュール](https://docs.ruby-lang.org/ja/latest/class/Enumerable.html, 'Ruby3.3公式リファレンスマニュアル：Enumerableモジュール')」で紹介されている全60メソッドを目的別に分類して紹介していきます。


## 1. 繰り返し操作したい
### 1-1. インデックス付きで各要素に対してループ処理したい【each_with_index】
「ループ処理する際にインデックスをつけたいねん」

そんな時は`each_with_index`。

eachは各要素をループ処理するだけですが、each_with_indexでは通し番号をつけることができます。

```ruby
['近本', '中野', '森下', '大山'].each_with_index {|name, index| puts "#{index}番#{name}"}

# => 0番近本
# => 1番中野
# => 2番森下
# => 3番大山
```
ただし、0以外の通し番号をつけたい場合は、`each.with_index`を使用するか、`each_with_index`内のブロックで`index + 1`する必要があります。
```ruby
['近本', '中野', '森下', '大山'].each.with_index(1) {|name, index| puts "#{index}番#{name}"}
['近本', '中野', '森下', '大山'].each_with_index {|name, index| puts "#{index + 1}番#{name}"}

# => 1番近本
# => 2番中野
# => 3番森下
# => 4番大山
```

### 1-2. 各要素を指定したオブジェクトとともに操作したい【each_with_object】

「ループ処理の時、なんか特定のオブジェクトを一緒に渡したいねん」

そんな時に活躍するのが`each_with_object`です。

与えられたオブジェクトと要素をブロックに渡してループ処理を行い、最初に与えられたオブジェクトを返却します。

例えば、ハッシュを渡した上で配列をループ処理すると、以下のように配列をハッシュに変換することができます。

```ruby
players = ['近本', '中野', '森下', '大山']
result = players.each_with_object({}) do |name, obj|
  obj[name] = "#{players.index(name) + 1}番"
end

puts result
# => {"近本"=>"1番", "中野"=>"2番", "森下"=>"3番", "大山"=>"4番"}
```

### 1-3. 逆順に繰り返したい【reverse_each】
「`each`を逆順に繰り返したいねん、でもわざわざ`sort`するのはめんどくさい」

要素を逆順に繰り返したい場合は`reverse_each`を使うことができます。

`sort`メソッドで並び替える必要がないので、意外と便利です。
```ruby
['近本', '中野', '森下', '大山'].reverse_each do |name|
  puts name
end

# => 大山
# => 森下
# => 中野
# => 近本
```

### 1-4. n個ずつ要素をまとめて処理したい【each_cons】
「先頭から指定個数グループ化したいねん」

そんな時は`each_cons`。

`each_cons`は連続するn個の要素をグループ化して処理します。

`each_cons`が要素を一つずつずらしながらグループ化するのが特徴です。
```ruby
(1..6).each_cons(3) { |group| p group }
# => [1, 2, 3]
# => [2, 3, 4]
# => [3, 4, 5]
# => [4, 5, 6]
```
### 1-5. 指定したサイズごとに要素を分割して処理したい【each_slice】
「先頭から指定個数で要素を分割したいねん」

そんな時は`each_slice`。

`each_slice`は要素を指定サイズごとに分割して処理します。

`each_cons`は要素を一つずつずらしながらグループ化しますが、`each_slice`は分割するだけです。

例えば要素数10の配列に`each_slice(4)`を指定すると、4・4・2で分割されます。
```ruby
(1..10).each_slice(4) { |slice| p slice }
# => [1, 2, 3, 4]
# => [5, 6, 7, 8]
# => [9, 10]
```
### 1-6. 要素を展開せずにそのまま取得したい【each_entry】
「普通にeachでループすると、キーと値でバラバラになるの嫌やねんなあ」

そんな時は`each_slice`。

`each_entry`は`each`と似ていますが、各要素をそのまま取得するためのメソッドです。

特に、通常の`each`では展開される要素をそのまま扱いたい場合に役立ちます。

`hash`オブジェクトの場合、通常の`each`ではキーと値が分解されますが、`each_entry`ではそのまま取得できます。
```ruby
{ a: 1, b: 2 }.each_entry do |entry|
  p entry
end
# => [:a, 1]
# => [:b, 2]
```

### 1-7. 繰り返しを続けたい【cycle】
「何回かループ処理自体継続して欲しいなあ」

そんな時は`cycle`。

`cycle`はループ処理自体を指定回数繰り返します。
```ruby
[1, 2, 3].cycle(2) { |x| puts x }
# => 1
# => 2
# => 3
# => 1
# => 2
# => 3
```


## 2. 要素の選択・フィルタリングをしたい
### 2-1. 条件に一致する要素を1つ取得したい【find・detect】
「条件に合う要素見つけたいなあ」

そんな時は`find`・`detect`。

`find`・`detect`メソッドは、最初に条件を満たす要素を取得します。

とりあえず、最初の1件を取得したい時によく使います。
```ruby
[1, 2, 3, 4].find { |n| n > 2 }
# => 3
```

### 2-2. 条件に一致する要素を全部取得したい【select・filter・find_all】
「いやいや、1件じゃなくて全部取得したいねん」

そんな時は`select`・`filter`・`find_all`があります。

これらのメソッドは条件を満たす全ての要素を取得します。

```ruby
[1, 2, 3, 4].select { |n| n.even? }
# => [2, 4]
```

### 2-3. 条件に一致する要素を変換して全部取得したい【filter_map】
「いやいや、取得するだけじゃなくて加工もしたいねん」

そんな時は`filter_map`です。

`filter_map`は条件を満たす要素を変換した結果を取得します。
```ruby
# 偶数を取得してさらに2倍にする
(1..10).filter_map { |n| n * 2 if n.even? }
# => [4, 8, 12, 16, 20]
```

### 2-4. 条件に一致しない要素を取得したい【reject】
「逆や、条件に一致しない要素が欲しいねん」

そんな時は`reject`。

文字通り、条件を満たさない要素を取得します。
```ruby
# 偶数ではない=奇数を取得
(1..10).reject { |n| n.even? }
# => [1, 3, 5, 7, 9]
```

### 2-5. 正規表現やクラス判定を活用して、条件に一致する複数の要素を取得したい【grep】
「絞り込む際に正規表現使いたいねん」
そんな時は`grep`。
`grep`を使うと、条件に一致する要素を配列で返します。
主に正規表現やクラス判定に便利です。
```ruby
result = ['apple', 'banana', 'cherry'].grep(/a/)
# => ["apple", "banana"]

result = [1, 'apple', :symbol].grep(String)
# => ["apple"]
```
ブロックを渡すことで、取得した要素を変換することも可能です。
```ruby
result = ['apple', 'banana', 'cherry'].grep(/a/) { |word| word.upcase }
# => ["APPLE", "BANANA"]
```

### 2-6. 正規表現やクラス判定を活用して、条件に一致しない複数の要素を取得したい【grep_v】
「grepの逆のことしたいけど、いちいち正規表現で逆の条件を書くのめんどくさいねん」

そんな時は`grep_v`があります。

`grep`とは逆で、条件に一致しない要素を配列で返します。
```ruby
result = ['apple', 'banana', 'cherry'].grep_v(/a/)
# => ["cherry"]
```
条件に一致するものを除外する際に便利です。

### 2-7. 条件に一致する最初の要素のindexを取得したい【find_index】
条件に一致する最初の要素のindexを取得したい気分の時もあるかもしれませんね。

そんな時は`find_index`が大活躍です。

`find_index`は条件を満たす最初の要素のインデックスを取得します。
```ruby
# 25より大きい最初の要素のindexを取得
[10, 20, 30, 40].find_index { |n| n > 25 }
# => 2
```


### 2-8. 最初の1個を取得したい【first】
「とりあえず先頭の要素が欲しいねん」

そんな時は直感的に`first`で配列や範囲の最初の要素を取得しましょう。
```ruby
[10, 20, 30, 40].first
# => 10
```

ちなみに、引数に数値を渡すことで、指定した数だけ先頭から取得できます。

`take`と同じですね。
```ruby
(1..10).first(5)
# => [1, 2, 3, 4, 5]
```

### 2-9. 最初のn個を取得したい【take】
「たまには`first`以外でカッコよく先頭から要素取得したいねん」

そんな時は`take`。

先頭から指定した数の要素を取得します。
```ruby
(1..10).take(3)
# => [1, 2, 3]
```

### 2-10. 最初のn個を除外したい【drop】
「逆や、先頭からいくつかだけ除外したいねん」

そんな時は`drop`を使って先頭から指定した数の要素を除外しましょう。

```ruby
(1..10).drop(3)
# => [4, 5, 6, 7, 8, 9, 10]
```
### 2-11. 条件を満たす間だけ要素を取得したい【take_while】
「条件を満たす間だけ要素を全部取得したいねん。`range`効かせたいねん」

そんな時は`take_while`。

条件が真の間だけ要素を取得します。
```ruby
(1..10).take_while { |n| n < 5 }
# => [1, 2, 3, 4]
```
### 2-12. 条件を満たす間だけ要素を除外したい【drop_while】
「`take_while`があるならきっと`drop_while`もあるんよね？」

もちろんあります。

`drop_while`は`take_while`の逆で、条件が真の間だけ要素を除外します
```ruby
(1..10).drop_while { |n| n < 5 }
# => [5, 6, 7, 8, 9, 10]
```

### 2-13. nilを除外したい【compact】
「`nil`さんはいらんなあ」

そんな時は`compact`。

配列から`nil`を除外できます。
```ruby
[1, nil, 2, nil, 3].compact
# => [1, 2, 3]
```

### 2-14. 重複を除外したい【uniq】
「同じ要素は取り除きたいなあ」

そんな時は`uniq`。

配列の要素から重複を取り除いてくれます。
```ruby
[1, 2, 2, 3, 3, 3].uniq
# => [1, 2, 3]
```

## 3. 変換
### 3-1. 各要素を変換したい【map・collect】
「要素をそれぞれ加工したいなあ」

そんな時は`map`・`collect`。

各要素を変換して新しい配列を返します。
```ruby
(1..5).map { |n| n * 2 }
# => [2, 4, 6, 8, 10]
```

### 3-2. 各要素を変換してフラットな状態にしたい【flat_map・collect_concat】
「要素も加工したいし、多重配列もフラットにしたいなあ」

そんな時は`fkat_map`・`collect_concat`。

各要素を変換してフラットな配列を返します。
```ruby
[[1, 2], [3, 4]].flat_map { |arr| arr.map { |n| n * 2 } }
# => [2, 4, 6, 8]
```

### 3-3. 配列に変換したい【to_a・entries】
「ハッシュや`range`オブジェクトを配列に変換したいなあ」

`Enumerable`オブジェクトを配列に変換するには`to_a`・`entries`メソッドを使用します。

```ruby
(1..5).to_a
# => [1, 2, 3, 4, 5]

(1..5).entries
# => [1, 2, 3, 4, 5]
```
ハッシュのキーや値を配列に変換することも可能です。
```ruby
{ a: 1, b: 2 }.to_a
# => [[:a, 1], [:b, 2]]
```
### 3-4. ハッシュに変換したい【to_h】
「キーと値でペアになってるからハッシュにしたいなあ」

配列やキー・値のペアを持つ`Enumerable`オブジェクトをハッシュに変換するには`to_h`メソッドを使用します。
```ruby
[[:a, 1], [:b, 2]].to_h
# => {:a=>1, :b=>2}
```

## 4. 真偽確認
### 4-1. 指定した要素が含まれているか確認したい【include?・member?】
「この値、要素に含まれてるんかなあ？」

そんな確認をしたい時は`include?`・`member?`。

特定の要素が含まれているか確認することができます。
```ruby
[1, 2, 3].include?(2)
# => true

[1, 2, 3].include?(4)
# => false
```

### 4-2. 全要素が条件を満たすか確認したい【all?】
「全部の要素、この条件満たしているんかなあ？」

そんな確認をしたいときは`all?`。

すべての要素が条件を満たしているか確認することができます。
```ruby
[2, 4, 6].all? { |n| n.even? }
# => true
[2, 4, 6, 7].all? { |n| n.even? }
# => false
```
なお、空のコレクションに対しては常に`true`を返却するので注意が必要です。
```ruby
[].all? { |n| n.even? }
# => true
```

### 4-3. 少なくとも一つの要素が条件を満たすか確認したい【any?】
「全部じゃなくてもええねん、一つでも条件満たしていたらええねん」

そんな確認をしたい時は`any?`。

少なくとも1つの要素が条件を満たしているか確認できます。
```ruby
[1, 2, 3].any? { |n| n.even? }
# => true
[1, 3, 5].any? { |n| n.even? }
# => false
```
なお、空のコレクションに対しては常に`false`を返却します。
```ruby
[].any? { |n| n.even? }
# => false
```

### 4-4. 条件を満たす要素が一つもないことを確認したい【none?】
「`all?`の逆をしたいねん」

そんな時は`none?`。

すべての要素が条件を満たさない場合に`true`を返します。
```ruby
[1, 2, 3].none? { |n| n > 3 }
# => true
[1, 2, 5].none? { |n| n > 3 }
# => false
```
なお、`all?`と同じく空のコレクションに対しては常に`true`を返却するので注意が必要です。
```ruby
[].none? { |n| n > 3 }
# => true
```


### 4-5. 条件を満たす要素が一つだけあることを確認したい【one?】
「1個だけやで、1個だけ条件を満たして欲しいんや」

そんな時は`one?。`

条件を満たす要素が1つだけの場合に`true`を返します。

複数ある場合はちゃんと`false`を返すのが`any?`との違いです。
```ruby
[1, 2, 3].one? { |n| n.odd? }
# => false
[1, 2, 4].one? { |n| n.odd? }
# => true
```
なお、空のコレクションに対しては常に`false`を返却します。
```ruby
[].one? { |n| n.odd? }
```


## 5. 要素のグループ化・分割
### 5-1. 評価結果に基づいてグループ化したい【group_by】
「特定の条件でグループ分けしたいなあ」

そんな時は`group_by`。

評価結果をキーとして要素をグループ化することができます。
```ruby
[1, 2, 3, 4, 5].group_by { |n| n.even? }
# => {false=>[1, 3, 5], true=>[2, 4]}
```

### 5-2. 評価結果が変化するごとにグループ化したい【chunk】
「要素を評価して、結果が変わるたびにグルーピングしたいなあ」

そんな時は`chunk`。

要素を評価し、その結果が変わるたびにグループを作成できます。
```ruby
[1, 2, 2, 3, 3, 4].chunk { |n| n.even? }.to_a
# => [[false, [1]], [true, [2, 2]], [false, [3, 3]], [true, [4]]]
```

### 5-3. 条件を満たす間、隣接する要素を同じグループにまとめたい【chunk_while】
「条件を満たしている間だけ、前後の要素とまとめたいなあ」

そんな時は`chunk_while`。

指定した条件が`true`である間、隣接する要素を同じグループにまとめてくれます。
```ruby
[1, 2, 3, 1, 2, 1].chunk_while { |a, b| a < b }.to_a
# => [[1, 2, 3], [1, 2], [1]]
```

### 5-4. 条件が変化するタイミングで切り分けたい【slice_when】
「条件が変化するタイミングで要素を切り分けたいなあ」

そんな時は`slice_when`。

条件が変わるタイミングで要素を分割してくれます。
```ruby
[1, 2, 3, 1, 2, 1].slice_when { |a, b| a > b }.to_a
# => [[1, 2, 3], [1, 2], [1]]
```
### 5-5. 条件が真になる直後で分割したい【slice_after】
「条件が真になったらその直後で分割したいなあ」

そんな時は`slice_after`。

条件が`true`になる要素の直後で分割します。
```ruby
[1, 2, 3, 4, 5].slice_after { |n| n.even? }.to_a
# => [[1, 2], [3, 4], [5]]
```
### 5-6. 条件が真になる直前で分割したい【slice_before】
「逆に条件が真になる直前で分割したいなあ」

そんな時は`slice_before`。

条件が`true`になる要素の直前で分割します。
```ruby
[1, 2, 3, 4, 5].slice_before { |n| n.odd? }.to_a
# => [[1], [2, 3], [4, 5]]
```
### 5-7. 条件の一致有無で分割したい【partition】
「条件を満たすかどうかで分割したいねんなあ」

そんな時は`partition`。

指定した条件に一致する要素と一致しない要素を2つのグループに分けます。

`group_by`とは違って、`partition`はあくまでも条件に一致するかどうかの2パターンでしか分類できません。

```ruby
[1, 2, 3, 4, 5].partition { |n| n.even? }
# => [[2, 4], [1, 3, 5]]
```

## 6. 並び替え
### 6-1. 要素を並び替えたい【sort】
「要素を順番に並び替えたいねん」

そんな時は`sort`を使いましょう。

要素を昇順に並び替えることができます。
```ruby
[5, 3, 1, 4, 2].sort
# => [1, 2, 3, 4, 5]
```

「いやいや、降順で頼みますわ」

という場合は、ブロックを渡します。
```ruby
[5, 3, 1, 4, 2].sort { |a, b| b <=> a }
# => [5, 4, 3, 2, 1]
```
### 6-2. 指定した基準で並び替えたい【sort_by】
「単純に並び替えるんじゃなくて、指定した基準で並び替えたいねん」

そんな時は`sort_by`です。

`sort_by`を使うと、指定した基準で並び替えることができます。

ブロックで比較基準を指定します。

```ruby
players = [
  { name: '近本', age: 30 },
  { name: '中野', age: 28 },
  { name: '森下', age: 24 },
  { name: '大山', age: 30 }
]

players.sort_by { |player| player[:age] }
# => [{:name=>"森下", :age=>24}, {:name=>"中野", :age=>28}, {:name=>"近本", :age=>30}, {:name=>"大山", :age=>30}]
```

## 7. 集計・計算
### 7-1. 要素の合計を計算したい【sum】
「要素内を合計したいなあ」

そんな時は`sum`。

要素の合計値を計算できます。
```ruby
(1..5).sum
# => 15
```

ブロック内には式を渡すこともできるので、各要素を2倍して合計するみたいなことも可能です。
```ruby
(1..5).sum { |n| n * 2 }
# => 30
```

### 7-2. 要素の個数をカウントしたい【count】
「要素自体、何個あるか数えたいなあ」

そんな時は、`count`で要素の個数をカウントすることができます。

```ruby
[1, 2, 3, 4, 5].count
# => 5
```

また引数やブロックに条件を渡してあげると、その条件に合った要素の個数も取得してくれて便利です。
```ruby
[1, 2, 3, 4, 5].count { |n| n.even? }
# => 2
```

### 7-3. 要素の出現回数をカウントしたい【tally】
「りんご、バナナ、みかん、それぞれ何個出てきたん？」

そんな要素の出現回数をカウントする時に便利なのが`tally`メソッドです。

```ruby
['apple', 'apple', 'banana', 'orange'].tally #=> {"apple"=>2, "banana"=>1, "orange"=>1}
```

ハッシュを使うことで結果を加算していくこともできます。
```ruby
h = {}
[:apple, :banana, :orange].tally(h)
[:apple, :banana, :lemon].tally(h)

p h # => {:apple=>2, :banana=>2, :orange=>1, :lemon=>1}
```

### 7-4. 最大値を取得したい【max】
「シンプルに一番大きい値を知りたいねん」

そんな最大値を取得してくれるのが`max`メソッドです。

```ruby
[1, 5, 3, 4, 2].max
# => 5
```
ただし、該当する要素が複数存在する場合、どの要素を返すかは不定なことに注意しましょう。

### 7-5. 特定の条件下で最大値を取得したい【max_by】
「特定の条件に絞って、最大値を取得したいねん」

そんな`max`に条件を追加したい場合は`max_by`。

指定した基準での最大値を取得できます。

```ruby
players = [
  { name: '近本', age: 30 },
  { name: '中野', age: 28 },
  { name: '森下', age: 24 }
]
players.max_by { |player| player[:age] }
# => {:name=>"近本", :age=>30}
```
ただし、`max`と同じく該当する要素が複数存在する場合、どの要素を返すかは不定なことに注意しましょう。

### 7-6. 最小値を取得したい【min】
「最大値じゃなくて最小値を取得したいねん」

そんな時は`max`の逆なので`min`です。

要素の最小値を取得できます。
```ruby
[1, 5, 3, 4, 2].min
# => 1
```
### 7-7. 特定の条件下で最小値を取得したい【min_by】
「ということは、特定の条件に絞って、最小値を取得するのは`min_by`？」

おっしゃる通りです。

`min_by`は指定した基準での最小値を取得できます。
```ruby
players = [
  { name: '近本', age: 30 },
  { name: '中野', age: 28 },
  { name: '森下', age: 24 }
]
players.min_by { |player| player[:age] }
# => {:name=>"森下", :age=>24}
```
### 7-8. 最小値と最大値を両方取得したい【minmax】
「最小値と最大値、どっちも取得する欲張りなことしたいねん」

`minmax`なら最小値と最大値を同時に取得できます。

```ruby
[1, 5, 3, 4, 2].minmax
# => [1, 5]
```
### 7-9. 特定の条件下で最小値と最大値を両方取得したい【minmax_by】
「今までの流れからすると、`minmax`があれば`minmax_by`もあるんやろか？」

ありますね。

`minmax_by`を使うと、指定した基準で最小値と最大値を同時に取得できます。

```ruby
players = [
  { name: '近本', age: 30 },
  { name: '中野', age: 28 },
  { name: '森下', age: 24 }
]
players.minmax_by { |player| player[:age] }
# => [{:name=>"森下", :age=>24}, {:name=>"近本", :age=>30}]
```

### 7-10. 要素を累積して計算したい【inject・reduce】
「それぞれの要素について初期値を渡して累積計算したいなあ」

そんな時は、`inject`や`reduce`を使うと、要素を累積的に処理できます。

```ruby
(1..5).inject(100) { |sum, n| sum + n }
# => 115
```
初期値を省略すると、最初の要素が初期値として使用されます。
```ruby
(1..5).reduce(:+)
# => 15
```
## 8. その他の汎用操作
### 8-1. 複数のEnumerableを連結したい【chain】
「複数のEnumerableさん達を合体させたいなあ」
そんな時は`chain`。
文字通り、複数のEnumerableを連結し、1つのEnumerableとして扱います。
連結した結果は遅延評価されるため、大量のデータを扱う際にも便利です。
```ruby
enum1 = [1, 2, 3]
enum2 = [4, 5, 6]
enum3 = [7, 8, 9]

result = enum1.chain(enum2, enum3).to_a
# => [1, 2, 3, 4, 5, 6, 7, 8, 9]
```
### 8-2. 遅延評価でEnumerableを処理したい【lazy】
「この配列、要素多すぎてめっちゃ重たいやん。パフォーマンス改善したいわ」

そんな時は`lazy`。

`lazy`を使うと、遅延評価のEnumerableを生成できます。

大きなデータや無限リストの操作に適しています。

```ruby
lazy_enum = (1..Float::INFINITY).lazy
result = lazy_enum.select { |n| n % 2 == 0 }.first(5)
# => [2, 4, 6, 8, 10]
```
この例では、無限リストから最初の5個の偶数を効率よく取得しています。
### 8-3. 行列変換したい【zip】
「対応する要素ごとに行列変換したいけど、そんな高度なことできるんかなあ」

Rubyは行列変換にも対応しています。

`zip`を使うと、複数の`Enumerable`を対応する要素ごとにまとめて配列を生成します。

行列変換や関連付けに役立ちます。
```ruby
names = ['近本', '中野', '森下', '大山']
ages = [30, 28, 24, 30]

result = names.zip(ages)
# => [["近本", 30], ["中野", 28], ["森下", 24], ["大山", 30]]
```
ブロックを渡すことで、各要素を直接処理することも可能です。
```ruby
names.zip(ages) { |name, age| puts "#{name}は#{age}歳です。" }
# => 近本は30歳です。
# => 中野は28歳です。
# => 森下は24歳です。
# => 大山は30歳です。
```

## 9. まとめ
`Enumerable`全60メソッドを紹介しました。

たくさんありましたね。

全部覚えるのは難しいかもしれません。

でも、こんなことできるメソッドあるんだなとぼんやり知っているだけでもメソッドの幅が広がると思います！