JavaScriptで数値配列の合計を求める:forEach()とreduce()の処理速度を徹底比較
ES6で導入された配列メソッドのうち、forEach()とreduce()はどちらも配列の各要素にアクセスして処理を行うことができます。しかし、巨大な数値配列の合計を求める場合、どちらのメソッドがより高速に動作するのでしょうか。本記事では、両者の実行時間を実際に計測して比較します。
ここで実際に巨大な配列を用意するのは現実的ではないため、合計を求める処理を大量の回数(反復)繰り返し実行することで、巨大な配列を扱う状況をシミュレーションします。
コード例
それでは、比較用のコードを見てみましょう。
const arr = [1, 4, 4, 54, 56, 54, 2, 23, 6, 54, 65, 65];
const reduceSum = arr => arr.reduce((acc, val) => acc + val);
const forEachSum = arr => {
let sum = 0;
arr.forEach(el => sum += el);
return sum;
};
const iterations = 1000000000;
console.time('reduce');
for(let i = 0; i < iterations; i++){
let sumReduce = reduceSum(arr);
};
console.timeEnd('reduce');
console.time('forEach');
for(let j = 0; j < iterations; j++){
let sumForEach = forEachSum(arr);
};
console.timeEnd('forEach');このコードでは、reduce()を使って合計を求めるreduceSumと、forEach()を使って合計を求めるforEachSumの2つの関数を定義しています。そして、それぞれの関数を10億回呼び出し、console.time()とconsole.timeEnd()で所要時間を計測します。
実行結果
コンソールには以下のような出力が表示されます。
reduce: 19.058s forEach: 45.204s
結果の考察
この結果から、Array.prototype.reduce()とArray.prototype.forEach()の処理時間の比は、おおよそ1 : 1.4であることが分かります。つまり、reduce()の方が約1.4倍高速です。
この差が生じる主な理由は以下の通りです。
- reduce()は累積に最適化されている:アキュムレータを使った値の集約という用途に特化しており、JavaScriptエンジンによる最適化が効きやすい構造です。
- forEach()はコールバック内で外部変数を書き換える:クロージャを介して外部の
sum変数にアクセス・更新するため、エンジンが最適化を行いにくくなります。
したがって、単に配列の合計を求めるだけであれば、パフォーマンスの観点からreduce()を使用するのが望ましいと言えます。ただし、実際の開発では配列のサイズが小さいケースが多く、体感できる差はほとんどないため、コードの可読性を重視して選択するのも有効な判断です。
-
JavaScriptで配列内の数値と文字列数値を区別して合計差を計算する方法
問題今回は、整数の数値型と文字列型が混在した配列を受け取るJavaScript関数を作成します。関数の仕様は以下の通りです。文字列として表現された整数をすべて合計する数値型の整数の合計から、その文字列整数の合計を引いた値を返すコード例以下がその実装コードです。const arr = [5, 2, '4', '7', '4', 2, 7, 9]; const integerDifference = (arr = []) => { let res = 0; &n
-
JavaScriptで数値配列の分散を計算する方法
問題昇順にソートされた数値の配列を受け取り、その分散(Variance)を計算するJavaScript関数を作成する必要があります。分散とは、一連の数値が平均値からどれだけばらついているかを表す統計量で、まず平均値を求め、その平均との差の二乗和をデータ数で割ることで計算できます。計算式まず、平均値(M)は次のように定義されます。$Mean (M) = ( \sum_{i=0}^{n-1} arr[i])$ / n続いて、分散(V)は各要素と平均値の差を二乗し、それらを合計してデータ数で割った値になります。Variance (V) = $(\sum_{i=0}^{n-1} (arr[i] - M