【Ruby Silver】inject メソッド

## 自己紹介
はじめまして、はる（[@lemonade_37](https://twitter.com/lemonade_37)）と申します。
エンジニアとして働き始めて約1年が経過しました🐣


## 概要
昨年 Ruby Silver を受験した際に `inject` メソッドの理解に時間がかかったため、
このメソッドについて学習したことを記事にまとめました。



### 環境
- Ruby 3.4.1

:::note warn
わかりにくい箇所や、紹介した方法よりも良い方法をご存知の方は教えて頂けると嬉しいです🙇
:::


## inject メソッド 基本の使い方
```ruby:基本の使い方①
inject(初期値){ |result, item| result + item }
# result + item の部分の計算式は自由に変更可
```

```ruby:基本の使い方②
inject(symbol)
```


## inject メソッドとは
- 配列などの要素を1つずつ繰り返してブロック内で要素を注入し処理するメソッドです。
処理を行い、**最終的には1つの値にまとめます** 。

- たたみこみ演算を行います。[1)](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/inject.html)

このように言葉で表しても、自分はイメージがつかなかったので、図にしました。

![IMG_1502.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3471604/e256f83e-f52f-48a1-9490-51024e17d97b.png)

```ruby
array = [1, 2, 3, 4, 5]
p array.inject{ |sum, n| sum + n }
#=> 15
```

こちらの図のコードでは配列の要素の数（今回だと5個あるので5回）だけ繰り返しを行います
1回目のループでは、`n = 1` を代入します。初回なので `sum = 0` です。
`sum + n` は `0 + 1 = 1` となります。
2回目のループでは、`n = 2` を代入します。`sum` には **これまでの処理結果** が入るので、
`sum = 1` です。`sum + n` は `1 + 2 = 3` となります。
3回目のループでは、`n = 3` を代入します。`sum` には これまでの処理結果 が入るので、
`sum = 3` です。`sum + n` は `3 + 3 = 6` となります。
4回目のループでは、`n = 4` を代入します。`sum` には これまでの処理結果 が入るので、
`sum = 6` です。`sum + n` は `6 + 4 = 10` となります。
5回目のループでは、`n = 5` を代入します。`sum` には これまでの処理結果 が入るので、
`sum = 10` です。`sum + n` は `10 + 5 = 15` となります。


:::note info
配列内の要素を1つずつ取り出し、代入して計算式を計算し、その計算結果を次のループに引き継いでいきます。
これを配列の要素の数だけ繰り返して、最終的に1つの値にまとめます。
:::

## inject メソッドとよく一緒に使われるもの💡
### たたみ込み演算を行う二項演算子
- `:+` … 配列の中身を全て **足し合わせる**
- `:-` … 2つの配列の和集合からの **差分**
- `:*` … 配列の中身を全て **掛け合わせる**
- `:<<` … 配列の要素が文字列のとき、**文字列を連結する**

### 合わせて使われるメソッド
- `succ` … `&:succ` のように書かれている時は、すべての要素に対して、**「次」の整数をとる**
    ```ruby:例
    p 1.succ
    #=> 2

    p -1.succ
    #=> 0
    ```
    　
- `abs` … **絶対値** を返す（負の符号が外れる）
    ```ruby:例
    p -123.abs
    #=> 123
    ```
    　
- `abs2` … 絶対値の **2乗** を返す


## 実行例
当時学習時に動かして試していたコード [(Gist)](https://gist.github.com/satou-haruka-37/0f472ebce69270c3d54bda4241904303) も添付します。
（[paiza.io](https://paiza.io/ja/projects/new?language=ruby)で動かしていました）

```ruby:sample
a = [-1,2,3,4,5]
b = (4..6).to_a

puts "b：#{b}"

puts "---"

p a.inject(:+) + b.inject(:+)

puts "---"

p (a|b).inject(:-).abs
p (a|b).inject(:-).abs + (a&b).inject(:+)

puts "---"

p (a|b).inject(:*)
p b.inject(0){|x,y| x + y ** 3}
p (a|b).inject(:*) + b.inject(0){|x,y| x + y ** 3}

puts "---"

# 複雑な式も分解して計算すれば読み解ける例
p (a||b).map(&:succ) # 0が含まれているためinject(:*)で掛け合わせると0
p (a && b).inject(:*).abs2
p (a||b).map(&:succ).inject(:*) * (a && b).inject(:*).abs2 # 結局ここまでは全て0
p ((a||b).map(&:succ).inject(:*) * (a && b).inject(:*).abs2 + 29 ) # 最後の+29 だけ0じゃない
```

```terminal:sample 実行結果
b：[4, 5, 6]
---
28
---
21
30
---
-720
405
-315
---
[0, 3, 4, 5, 6]
14400
0
29
```



## さいごに
最初は苦手意識があったメソッドでしたが、動きを理解すると読めるようになりました。
まだ複雑な処理の場合、理解に時間はかかりますが、せっかく資格勉強で覚えたことを無駄にしないよう、読み慣れていきたいです💎



　
## 参考記事
#### 引用記事
1）[Enumerable#inject (Ruby 3.4 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/inject.html)
 
#### 参考記事
- [injectメソッド](https://qiita.com/wangqijiangjun/items/9e56a5313ae780ec7f11)
- [【Ruby】`inject(:+)`によるリファクタリングと`:+`の意味](https://qiita.com/terufumi1122/items/c060d86f966e566a0520)