自分はWeb制作からプログラミングを始めたのでJavaScriptのreduceについて存在すら知りませんでした。
ReactのようなモダンJSを勉強し始めた時にreduceが登場して少し手こずったことがあったので、reduceの使い方を共有です。
また動画もあるので必要に応じて使ってください。
JavaScriptにおけるreduceの使い方
まずは簡単な例で説明していきます。
const number = [100,200,300];
const sum = number.reduce((pre,current) => {
return pre + current;
});
console.log(sum); // 600と出力される
reduceは簡単に言うと「合算」のような動作をします。
上記の例だと配列numberのなかに3つの数字があり、それらを足し合わせたものを返しています。
reduceはコードの書き方を見てもらうと分かるように、繰り返し処理のような形にもなっています。
配列のなかを順番に見て処理していくので、繰り返し処理と言っても良いかもしれません。
またreduceでは上記でいうpre、currentのように2つの引数を取ることが多いです。
先ほど繰り返し処理と似ていると言ったように、配列のなかの要素を左から見ていきます。
左から見て「1個前に見た要素」「今見ている要素」という具合に、2つの引数に値が順番に代入されていきます。
上記の例だと、
①「pre = 0, current = 100」
②「pre = 100, current = 200」
③「pre = 200, current = 300」
という順番に引数に値が代入されました。
ちなみに上記のような数字を合計するだけであれば、for文でも同じことができます。
const number = [100,200,300];
let sum = 0;
for(const num of number){
sum += num;
}
console.log(sum); // 600と出力される
こちらの方が馴染みがあると思いますが、reduceの方が少しばかり短く書くことができます。
今回やった数字の合算であればforでもreduceでも自分の使いやすい方で大丈夫です。
ただしfor文の場合の場合、「let sum=0;」のように初期値(合計値)を先に宣言しておく必要があります。
reduceであれば引数の中に初期値を設定して、戻り値で合計値を返してくれるのでコード量が減りやすくなります。
const cartItems = [
{ name: 'aaa', price: 100 },
{ name: 'bbb', price: 200 },
{ name: 'ccc', price: 300 },
];
// for文で書く場合
let total = 0;
cartItems.forEach((item) => {
total += item.price;
});
console.log(total); // 600と出力される
// reduce文で書く場合
let total = cartItems.reduce((current, item) => current + item.price, 0);
console.log(total); // 600と出力される
JavaScriptのreduceでは配列の合体もできる
reduceでは配列同士を合体して1つの配列にすることもできます。
const array = [["aaa","bbb"],["ccc","ddd"]];
const mergeArray = array.reduce((pre, current) => {
return pre.concat(current);
});
console.log(mergeArray); // ["aaa","bbb","ccc","ddd]と出力される
実際のところ配列の合体は「スプレッド構文」というものの方がよく使われるのですが、初心者には少し難しいのでreduceから覚えると良いかと思います。
また上記のように配列の合体では左の配列が先に来るように合体します。
例えば右の配列から足したいときはreduceRightという専用の関数がJavaScriptには用意されています。
const array = [["aaa","bbb"],["ccc","ddd"]];
const mergeArray = array.reduceRight((pre, current) => {
return pre.concat(current);
});
console.log(mergeArray); // ["ccc","ddd","aaa","bbb"]と出力される
JavaScriptのreduceを使ったグルーピング
reduceは合体ができるためグルーピングすることにも利用できます。
以下のような配列があったとします。
const staff = [
{ name: 'yamada', lang: 'js' },
{ name: 'tanaka', lang: 'php' },
{ name: 'yoshida', lang: 'js' },
{ name: 'suzuki', lang: 'php' },
];
オブジェクトのnameプロパティには名前があり、langプロパティにはプログラミング言語があります。
配列staffをオブジェクトのlangプロパティでグルーピングすることが可能です。
const staff = [
{ name: 'yamada', lang: 'js' },
{ name: 'tanaka', lang: 'php' },
{ name: 'yoshida', lang: 'js' },
{ name: 'suzuki', lang: 'php' },
];
// ここから追加
const result = staff.reduce((arr, person) => {
const lang = person.lang;
if (arr[lang] == null) arr[lang] = [];
arr[lang].push(person.name);
return arr;
}, {});
console.log(result);
こちらはlangプロパティをインデックス番号に変換して、それぞれに該当するname属性で配列を作り直すコードです。
グルーピング自体にはgroupbyというメソッドが最近登場したので、reduceでやることは減りましたが一つの方法として覚えておくと良いでしょう。
JavaScriptのreduceの注意点
ここまでで何となくreduceの動作が分かってきたかと思いますので、reduceを使う上での大事なポイントを共有します。
reduceは配列にのみ使用できる
reduceは配列にのみ使える関数のため、オブジェクトには使うことができません。
const data = {id: "0001", name: "AAA", age: 20};
const result = data.reduce((sum, num) => {
return sum + num;
}, 0);
console.log(result); // エラーになる
一方で配列の中の要素がオブジェクトになっている場合は問題ありません。
const dataList = [
{
number: 1,
name: "AAA"
},
{
number: 3,
name: "BBB"
},
{
number: 5,
name: "CCC"
},
];
const listResult = dataList.reduce((sum, num) => {
return sum + num.number;
}, 0);
console.log(listResult); // 9と出力される