JavaScriptのreduceの使い方: 配列を走査し値を蓄積する

16, 2020-08-15

目次

JavaScriptのreduceの使い方

JavaScriptの配列にはreduceメソッドがあります。
これの使い方を解説します。

↓はreduceのサンプルコードです。

const arr = [1, 2, 3]
const result = arr.reduce((acc, cur) => acc + cur)

console.log(result)
// 6

reduceの動作

reduceは最初はわかりづらいですが、原理がわかれば簡単です。
reduceは第1引数に関数を渡せます。
この関数の第1引数には「蓄積された値」、第2引数には「現在の要素」が渡されます。
「蓄積された値」は関数の戻り値のことです。

たとえば[1, 2, 3]という配列のreduceを呼び出したとします。
そうするとreduceは配列の先頭の要素から順に辿っていきます。

const arr = [1, 2, 3]
const result = arr.reduce((acc, cur) => acc + cur)

console.log(result)
// 6

acc(accumulator)には初期値として配列の先頭の要素が渡されます。
そしてcur(current value)にはその次の要素が渡されます。
関数の戻り値は次の走査でaccになります。

↓の動作を見てみてください。

const arr = [1, 2, 3, 4]
const result = arr.reduce((acc, cur) => {
    console.log(`acc: ${acc}, cur: ${cur}`)
    return acc + cur
})

console.log(result)

出力結果。

acc: 1, cur: 2
acc: 3, cur: 3
acc: 6, cur: 4
10

Accumulatorって?

Accumulator(アキュムレーター)は和訳すると

蓄積者、蓄財家、蓄電池、累算器

のような意味を持ちます。
つまり計算の結果を溜めていく蓄財家ということですね。

reduceのコールバック関数

reduceの第1引数に渡せるのはアロー関数普通の関数です。

const arr = [1, 2, 3]
const result = arr.reduce((acc, cur) => {
    return acc + cur
})
const arr = [1, 2, 3]
const result = arr.reduce(function (acc, cur) {
    return acc + cur
})

reduceのコールバック関数の引数

reduceに渡す関数の引数は↓のようになっています。

  • 第1引数: 蓄積された値

  • 第2引数: 現在の要素

  • 第3引数: 現在の添え字

  • 第4引数: 走査中の配列

これらは簡単なコードで確認することが出来ます。

const arr = [1, 2, 3, 4]
const result = arr.reduce((acc, cur, index, me) => {
    console.log(`acc: ${acc}, cur: ${cur}, index: ${index}, me: ${me}`)
    return acc + cur
})
acc: 1, cur: 2, index: 1, me: 1,2,3,4
acc: 3, cur: 3, index: 2, me: 1,2,3,4
acc: 6, cur: 4, index: 3, me: 1,2,3,4

添え字が1から始まってる点に注意してください。
添え字0の要素はreduceの初期値(accの値)として使われています。
よって走査は添え字1から始まります。

reduceの初期値

reduceには初期値を明示的に渡せます。
reduceの第2引数に初期値を渡すと、reduceはその初期値から走査を開始します。

const arr = [1, 2, 3, 4]
const result = arr.reduce((acc, cur) => {
    console.log(`acc: ${acc}, cur: ${cur}`)
    return acc + cur
}, 10)

console.log(result)
// 20
acc: 10, cur: 1
acc: 11, cur: 2
acc: 13, cur: 3
acc: 16, cur: 4
20

↑の場合、走査する配列は[1, 2, 3, 4]で合計は10ですが、初期値が10になっているので計算の結果は20になります。

reduceの使用例

reduceの使用例を紹介します。

配列の合計値を得る

すでに何度も紹介してますが、配列の合計値を得るには↓のようにします。

const arr = [1, 2, 3, 4]
const result = arr.reduce((acc, cur) => acc + cur)

console.log(result)
// 10

reduceを使わない場合は↓のようなコードになります。

const arr = [1, 2, 3, 4]
let result = 0

for (const el of arr) {
    result += el
}

console.log(result)
// 10

要素の出現回数を数える

配列の要素の出現数を数えて、それらを保存したオブジェクトを返すサンプルです。
統計に使えそうですね。

const arr = ['Cat', 'Dog', 'Bird', 'Cat']
const result = arr.reduce((acc, key) => {
    if (key in acc) {
        acc[key]++
    } else {
        acc[key] = 1
    }
    return acc
}, {})

console.log(result)
// { Cat: 2, Dog: 1, Bird: 1 }

参考: Array.prototype.reduce() - JavaScript | MDN

reduceを使わない場合は↓のようなコードになります。

const arr = ['Cat', 'Dog', 'Bird', 'Cat']
let result = {}

for (const key of arr) {
    if (key in result) {
        result[key]++
    } else {
        result[key] = 1
    }
}

console.log(result)
// { Cat: 2, Dog: 1, Bird: 1 }

2次元配列を1次元配列にする

2次元配列を1次元にして平らにするサンプルです。

const arr = [[1, 2], [3, 4]]
const result = arr.reduce((acc, el) => {
    return acc.concat(el)
}, [])

console.log(result)
// [ 1, 2, 3, 4 ]

参考: Array.prototype.reduce() - JavaScript | MDN

reduceを使わない場合は↓のようなコードになります。

const arr = [[1, 2], [3, 4]]
let result = []

for (const el of arr) {
    result = result.concat(el)
}

console.log(result)
// [ 1, 2, 3, 4 ]

問題

Q1: reduceの走査で、最初に関数が呼ばれる時のaccの値として適当なものを答えよ

  1. 配列の1番目(0オリジン)の要素

  2. 配列の0番目(0オリジン)の要素

  3. reduceの第2引数

Q2: reduceに渡すコールバック関数の第4引数として適当なものを答えよ

  1. 蓄積された値

  2. 添え字

  3. 走査中の配列


答え
Q1: 2, 3
Q2: 3