以下コードは配列内の値の合計を求めます。
reduce に渡す関数の第1引数(a)はアキュムレータと呼ばれ、最終的に配列が変換された値になります。
以下のコードでは配列内の値の合計になります。
第2引数(x)は、配列内の値になります。
reduce の第2引数はアキュムレータの初期値です。
const arr = [1, 2, 3];
// ----reduceの引数------------------------
// 第1引数:関数
// 関数の引数 第1引数(a):アキュムレータ
// 第2引数(x):配列の値(arr)
// 第2引数:アキュムレータの初期値
const sum = arr.reduce((a, x) => a += x, 0);
console.log(sum); // 6
配列の値に対して順に reduce の第1引数に渡した関数が呼ばれます。
- 先ず最初は、a(アキュムレータ)の値は0で、配列の最初の値1に対して関数が呼ばれると、x は配列の値なので1となり、a += x の式から a は1となります。
- 次に配列の2番目の値2に対して関数が呼ばれると、x は配列の値なので2となり、a は1なので a += x の式から a は3となります。
- 次に配列の3番目の値3に対して関数が呼ばれると、x は配列の値なので3となり、a は3なので a += x の式から a は6となり、配列の値の合計が返されます。
reduce の第2引数を省略した場合は、配列の最初の値(1)がアキュムレータの初期値になります。
上記コードでは、reduce の第1引数に渡す関数をアロー関数にしていますが、より複雑な処理をしたい場合は、変数に入れた関数を渡します。
const arr = [1, 2, 3];
let fun = function (a, x) {
x = x*10
return a += x
}
const sum = arr.reduce(fun, 0);
console.log(sum); // 60
オブジェクトをアキュムレータとして使う
オブジェクトをアキュムレータとして使うこともできます。
以下のコードは配列内の要素(名前)を先頭文字ごとに別々の配列にまとめたオブジェクト生成します。
reduc の第2引数で、アキュムレータの初期値を空のオブジェクトに設定し、配列要素の先頭文字のプロパティがあるかチェックして、先頭文字のプロパティが無ければ空の配列のプロパティを作成し、現在の要素を追加 そのオブジェクト(アキュムレータ)を返します。
const names = ["Shimizu", "Tanaka", "Ando", "Adachi", "Takagi", "Suzuki",
"Yamada", "Inoue", "Sato", "Iida", "Okada"];
const nameAlphabet = names.reduce((a, x) => {
// アキュムレータ(オブジェクト)内に
// 配列要素の先頭文字のプロパティがあるかチェック
if (!a[x[0]])
a[x[0]] = []; // なければ空の配列のプロパティを作成
a[x[0]].push(x); // 現在の要素を追加
// console.log(a[x[0]]); // 途中経過を見るにはこれを有効に
return a; // オブジェクトを返す
}, {}); // アキュムレータの初期値をオブジェクトに
console.log(nameAlphabet);
/* 実行結果
{
S: [ 'Shimizu', 'Suzuki', 'Sato' ],
T: [ 'Tanaka', 'Takagi' ],
A: [ 'Ando', 'Adachi' ],
Y: [ 'Yamada' ],
I: [ 'Inoue', 'Iida' ],
O: [ 'Okada' ]
}
*/
文字列をアキュムレータとして使う
const words = ["Shimizu", "Tanaka", "Ando", "Ooenoki", "Takagi", "Suzuki", "Yamada", "Inoue", "Sato", "Iida", "Iwashimizu"];
const longWords = words.reduce(
(a, w) => w.length > 6 ? a + ", " + w : a,
"" // アキュムレータの初期値を文字列
).replace(", ", "");
console.log(longWords) // Shimizu, Ooenoki, Iwashimizu