序章

Reduce は、特にWebにある漠然とした説明では、理解するのが難しい方法です。 reduceは状態管理でよく使用されるため、理解することには多くの利点があります( Redux を考えてください)。

JavaScriptのreduce配列メソッドのシグネチャは次のとおりです。

arr.reduce(callback, initialValue);

用語

Reduceには、次のような用語が付属しています。 レデューサー&アキュムレータaccumulatorは最後の値であり、reducerは、1つの値に到達するために実行するアクションです。

reducer は1つの値と1つの値のみを返すため、reduceという名前になることを覚えておく必要があります。

次の典型的な例を見てください。

const value = 0; 

const numbers = [5, 10, 15];

for(let i = 0; i < numbers.length; i++) {
  value += numbers[i];
}

上記により、30(5 + 10 + 15)が得られます。 これは問題なく機能しますが、代わりにreduceを使用してこれを行うことができます。これにより、value変数を変更する必要がなくなります。

以下のコードも30を出力しますが、value変数(現在はinitialValueと呼んでいます)を変更しません。

/* this is our initial value i.e. the starting point*/
const initialValue = 0;

/* numbers array */
const numbers = [5, 10, 15];

/* reducer method that takes in the accumulator and next item */
const reducer = (accumulator, item) => {
  return accumulator + item;
};

/* we give the reduce method our reducer function
  and our initial value */
const total = numbers.reduce(reducer, initialValue)

上記のコードは少し紛らわしいように見えるかもしれませんが、内部では魔法は起こっていません。 reducerメソッドにconsole.logを追加して、accumulator引数とitem引数を出力してみましょう。

次のスクリーンショットは、コンソールに記録されたものを示しています。

Reduce Output

したがって、最初に気付くのは、配列に3値があるため、メソッドが3回呼び出されることです。 アキュムレータは、reduceに渡したinitialValueである0から始まります。 関数を呼び出すたびに、itemaccumulatorに追加されます。 メソッドの最後の呼び出しのaccumulatorの値は15で、item1515 + 15[X122X ]これが最終的な値です。 reducerメソッドはaccumulatoritemを返すことに注意してください。

これは、reduceの使用方法の簡単な例です。次に、より複雑な例を詳しく見ていきましょう。

Reduceを使用して配列をフラット化する

次の配列があるとしましょう。

const numArray = [1, 2, [3, 10, [11, 12]], [1, 2, [3, 4]], 5, 6];

そして、なんらかの奇妙な理由で、JavaScriptが.flatメソッドを削除したため、この配列を自分でフラット化する必要があるとしましょう。

したがって、配列がどれほど深くネストされていても、任意の配列をフラット化する関数を記述します。

function flattenArray(data) {
  // our initial value this time is a blank array
  const initialValue = [];

  // call reduce on our data
  return data.reduce((total, value) => {
    // if the value is an array then recursively call reduce
    // if the value is not an array then just concat our value
    return total.concat(Array.isArray(value) ? flattenArray(value) : value);
  }, initialValue);
}

numArrayをこのメソッドに渡して結果をログに記録すると、次のようになります。

Flatten Array Output

これは、非常に一般的な操作を非常に簡単にする方法の良い例です。

もう1つの例を見てみましょう。

最後の例-オブジェクト構造の変更

それで、新しいポケモンゲームが出てきたら、次のようなポケモンオブジェクトの配列を送信するサーバーがあるとしましょう。

const pokemon = [
  { name: "charmander", type: "fire" },
  { name: "squirtle", type: "water" },
  { name: "bulbasaur", type: "grass" }
]

このオブジェクトを次のように変更します。

const pokemonModified = {
  charmander: { type: "fire" },
  squirtle: { type: "water" },
  bulbasaur: { type: "grass" }
};

その目的の出力を取得するには、次のようにします。

const getMapFromArray = data =>
  data.reduce((acc, item) => {
    // add object key to our object i.e. charmander: { type: 'water' }
    acc[item.name] = { type: item.type };
    return acc;
  }, {});

このようにメソッドを呼び出すと、次のようになります。

getMapFromArray(pokemon)

目的の出力が得られます。

Pokemon Output

コードサンドボックスはこちらで確認できます。

結論

一見すると、reduceは、mapfilterのような他のJavaScript配列反復法よりも複雑に見えますが、構文、コアコンセプト、およびユース-ケースは、JavaScript開発者にとってもう1つの強力なツールになる可能性があることを理解しています。