カルキチブログ

JavaScriptの配列操作で困った時はこれ!reduceメソッドについてまとめてみた

JavaScriptでSPAだったり、バックエンドのロジック実装を行うときは複雑な配列操作やオブジェクト操作を行わなければいけないシチュエーションに遭遇することは珍しくないと思います。

今回は、複雑な配列操作やオブジェクト操作を行う際にとても便利な、reduceメソッドについてまとめてみました。

reduceメソッドとは?

reduceメソッドとは、配列のそれぞれの要素に対して、任意の処理を再起的に処理を実行し、単一の値を返却することができるメソッドです。

以下、MDNの引用です。

reduce() メソッドは、配列のそれぞれの要素に対してユーザーが提供した「縮小」コールバック関数を呼び出します。その際、直前の要素における計算結果の返値を渡します。配列のすべての要素に対して縮小関数を実行した結果が単一の値が最終結果になります。

引用:Array.prototype.reduce() - JavaScript | MDN

以下のサンプルコードは、配列arrayの中の数値を全て足していき、足し算した結果を返却する処理の例です。

const array = [1, 2, 3, 4, 5];

const result = array.reduce((prev, current, currentIndex, array) => {
  return prev + current;
});

// 15
console.log(result); 

第1引数に取ることができる値

reduceメソッドは引数に以下のような値を取ることができます。

  • prev・・・前回のcallbackの結果の値(currentの一つ前の要素)
  • current・・・現在処理が行われている要素
  • currentIndex・・・currentで処理されている要素のindex
  • array・・・処理対象の配列

prevにはcurrentで行なっている処理の一つ前の値が、currentには処理中の値が入るので、変数prevとcurrentをconsole.logで出力すると以下のようなログが出力されます。

const array = [1, 2, 3, 4, 5];

const result = array.reduce((prev, current, currentIndex, array) => {
  console.log(`prev: ${prev}`);
  console.log(`current: ${current}`);
  return prev + current;
});

// 15
console.log(result); 
prev: 1 current: 2 prev: 3 current: 3 prev: 6 current: 4 prev: 10 current: 5 15

第2引数に設定可能なinitialValueについて

reduceメソッドの第一引数には、4つの引数を渡すことができますが、第2引数にも値を設定することができます。

第2引数にはコールバック関数が初めて呼び出された時の初期値、initialValueを設定することができます。

第2引数にinitialValueを渡すと、第2引数で渡した初期値から処理を実行することができます。

下記のコードは「引数に取ることができる値」という項で紹介したサンプルコードを一部変更したものです。

第2引数に初期値を設定しているので、15という数値に配列arrayの中の数値を全て足していき、足し算した結果を返却するので、30という数値が返却されます。

const array = [1, 2, 3, 4, 5];

const result = array.reduce((prev, current, currentIndex, array) => {
  return prev + current;
}, 15);

// 30
console.log(result); 

reduceメソッドの使い道

個人的に特にこれは便利だなと思った使い方についてまとめてみました。

サンプルコードの実装例は以下の記事を参考にさせていただきました。

https://kde.hateblo.jp/entry/2018/10/13/065738

多次元配列を一次元配列にする

const array = [
  [
    { id: 1, category: 'sports', title: 'post1' }, { id: 2, category: 'sports', title: 'post2' }
  ],
  [
    { id: 3, category: 'entertainment', title: 'post1' }, { id: 4, category: 'entertainment', title: 'post2' }
  ],
];

const results = array.reduce((prev, current) => {
  return [...prev, ...current]
}, [])

// [
//   { id: 1, category: 'sports', title: 'post1' },
//   { id: 2, category: 'sports', title: 'post2' },
//   { id: 3, category: 'entertainment', title: 'post1' },
//   { id: 4, category: 'entertainment', title: 'post2' }
// ]
console.log(results);

reduce初めて使った時に一番感動したやつです。
reduceの第2引数のinitialValueにはオブジェクトや配列を渡すこともできます。

initialValueにオブジェクトや配列を渡すことで、配列やオブジェクトを渡すと処理の実行結果を含む新しい配列、オブジェクトを生成することもできます。

配列内の重複した値を削除する

const array = [
  { id: 1, category: 'sports', title: 'post1' },
  { id: 2, category: 'sports', title: 'post2' },
  { id: 3, category: 'sports', title: 'post2' },
  { id: 4, category: 'entertainment', title: 'post1' },
  { id: 5, category: 'entertainment', title: 'post5' }
];

const hasValue = (currentObj, prevAry) => prevAry.some(item => item.title === currentObj.title);

const results = array.reduce((prev, current) => {
  if (!hasValue(current, prev)) prev.push(current);
  return prev;
}, []);

console.log(results);

someを使って処理中の値にダブりがないかのチェックを行い、ダブってない時のみinitialValueに渡した配列に処理結果を代入するようなイメージです。

まとめ

  • reduceメソッドは、配列のそれぞれの要素に対して、任意の処理を再起的に処理を実行し、単一の値を返却することができる関数。
  • 第1引数には処理中の要素の一つ前の要素、処理中の要素、処理中の要素のインデックス、処理対象の配列をそれぞれ引数として渡すことができる。
  • 第2引数には初期値を設定することもできる。(配列やオブジェクトを渡すと処理の実行結果を含む新しい配列を生成することができる)
  • JSの配列操作で困ったら、reduce使っておけば高確率でなんとかなる(ちゃんと考えないとダメだけど、、、)

既存のreduceについて解説した記事でも、reduceは配列操作において最強みたいなこと書いている記事をちらほら見かけます。

実際、reduceは使いこなせるととても便利な関数ではあると思うので、皆さんも配列やオブジェクトの操作で困った時はreduceをぜひ使ってみてくださいね!

おまけ

最近バカほど忙しいです。

普段の開発業務と並行して求人サイトのリニューアルやったり、新たな案件(2件くらい追加されるっぽい)も増えるので、体持つかなって感じです。