reduceの使い方を整理した (JavaScript)

配列のメソッドである`reduce`を整理してみました。

### reduceの基本形

```javascript
const result = arrayData.reduce(
  // 第一引数
  (accumulator, currentValue, index, arr) => {},
  // 第二引数
  initialValue
)
// 構造がわかりやすい様に改行してます
```

**第一引数のコールバックの引数（最大4つ）：**
`accumulator`: 累積値（直前のループの結果）
`currentValue`: 現在のループの要素
`index`: 現在のループの配列インデックス *省略可
`arr`: reduceが呼ぶ配列そのもの *省略可

**第二引数**
initialValue: accumulatorの初期値 *省略可

### 配列の全ての要素の和を返すreduceの一番シンプルな使い方で中身を見てみます。
```javascript
const numbers = [1,2,3,4,5,6,7,8,9]
const result = numbers.reduce((accumulator, currentValue) => {
  console.log("accumulator", accumulator, "currentValue", currentValue)
  return accumulator + currentValue
})
console.log("result", result)
```
consoleはこう出力されます。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/6864f17b-c2a7-c5ee-ba73-f0898f2f2fd5.png)

配列の`0番目`がaccumulator(累積値)の初期値として使用されていることがわかります。
それ以降は`1番目`から順にループして、累積値に加算しているのがわかります。

累積値の初期値に任意の値を入れたい場合は、第二引数に初期値を入れます。
```javascript
const numbers = [1,2,3,4,5,6,7,8,9]

const initialValue = 0

const result = numbers.reduce((accumulator, currentValue) => {
  console.log("accumulator", accumulator, "currentValue", currentValue)
  return accumulator + currentValue
}, initialValue)
console.log("result", result)
```
これを実行すると、consoleはこう出力されます。
初期値が0になって、配列の０番目の値からループされていることがわかります。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/493d9ae2-2328-57ea-2294-3809c8703353.png)

では、全てのパラメーターをセットして実行してみます
```javascript
    const numbers = [1,2,3,4,5,6,7,8,9]

    const result = numbers.reduce((accumulator, currentValue, index, arr) => {
      console.log("accumulator", accumulator, "currentValue", currentValue, "index", index, "arr", arr)
      return accumulator + currentValue
    }, 0)
```

これを実行すると、consoleはこう出力されます。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/85fd7ca2-c2b8-2deb-ffad-430ffa15c30b.png)

indexは配列の何番目を処理してるかで、arrはreduceが処理している配列データです。なのでこの2つは省略されるケースが多いです。

まとめると、reduceは配列を順にループし、各回の結果を次の呼び出しに引き継ぐ事ができるという仕組みです。そして配列のループが終わったら、累計値を返します。

### forEachとの違い
forEachで以下の様に同じことできますが、reduceの方がいい理由としてはletで変数を宣言しなくていい事などが挙げられます。
```javascript
const numbers = [1,2,3,4,5,6,7,8,9]
let result = 0
numbers.forEach((value) => {
  result += value
})
```


### 応用
例えばこんな従業員のデータがあって、職種ごとの月間合計コストを算出したい場合、forEachで書こうとしたら大変ですが、reduceを使えば楽に書けます。

```javascript
const employees = [
  { id: 'QTA01', name: '山田太郎', job: 'エンジニア', monthlySalary: 500000 },
  { id: 'QTA02', name: '鈴木大輔', job: 'エンジニア', monthlySalary: 400000 },
  { id: 'QTA03', name: '渡部秀雄', job: '営業', monthlySalary: 450000 },
  { id: 'QTA04', name: '田中花子', job: '営業', monthlySalary: 520000 },
  { id: 'QTA05', name: '岡田三郎', job: '経理', monthlySalary: 410000 },
  { id: 'QTA06', name: '田嶋圭一', job: '経理', monthlySalary: 360000 },
]

const result = employees.reduce((accumulator, currentValue) => {
  if (!accumulator[currentValue.job]) {
    accumulator[currentValue.job] = 0
  }
  accumulator[currentValue.job] += currentValue.monthlySalary
  return accumulator
}, {})
```

結果はこうなります。
```javascript
{ エンジニア: 900000, 営業: 970000, 経理: 770000 }
```

この様な**分類と集計処理にreduceは便利**です。

他にもreduceを使った便利なデータ処理は色々あると思いますので、都度追加していきます。