JavaScriptでスライディングウィンドウを使って連続する数値の平均を効率的に計算する方法
整数の配列 arr を第1引数に、数値 num(arr.length 未満)を第2引数として受け取る JavaScript 関数を作成する必要があります。この関数は、配列内に存在するすべての「連続する num 個の要素」の平均を格納した新しい配列を構築して返します。
例
たとえば、入力が次のような場合を考えてみましょう。
const arr = [1, 2, 3, 4, 5]; const num = 2;
このとき、期待される出力は次の通りです。
const output = [1.5, 2.5, 3.5, 4.5];
これは、サイズ 2 の連続するウィンドウが (1, 2)、(2, 3)、(3, 4)、(4, 5) の 4 パターン存在し、それぞれの平均が 1.5、2.5、3.5、4.5 となるためです。
実装コード
以下が実際の実装例です。
const arr = [1, 2, 3, 4, 5];
const num = 2;
const findContiniousAverage = (arr = [], num = 1) => {
if (num > arr.length) {
return [];
}
const res = [];
let sum = 0;
let left = 0, right = 0;
// 最初のウィンドウ(num個分)の合計を計算
for (; right < num; right++) {
sum += arr[right];
}
res.push(sum / num);
// ウィンドウを1つずつ右へスライドさせながら平均を計算
for (; right < arr.length; right++, left++) {
sum -= arr[left];
sum += arr[right];
res.push(sum / num);
}
return res;
};
console.log(findContiniousAverage(arr, num));
console.log(findContiniousAverage(arr));
出力結果
コンソールには次のように表示されます。
[ 1.5, 2.5, 3.5, 4.5 ] [ 1, 2, 3, 4, 5 ]
num を省略して呼び出した場合は、デフォルト引数により num = 1 として処理されるため、各要素がそのまま返されています。
コードの解説
この実装の核心となっているのは、スライディングウィンドウ(移動窓)と呼ばれるテクニックです。
- まず最初の
num個の要素の合計を計算し、最初の平均を求めます。 - その後は、ウィンドウを 1 つ右にずらすたびに、「左端の値を合計から引き、新しく入ってくる右端の値を加算する」だけで新しい合計を得られます。
- 各ウィンドウごとに合計をゼロから再計算しないため、全体の計算量は O(n) に抑えられます。毎回再計算する素朴な実装(O(n × num))と比べて、大きな配列でも高速に動作します。
- さらに、
numが配列の長さより大きい場合には空配列を返すガード節を設けており、不正な入力に対しても安全に対応できます。
このように、累積的な合計を上手く再利用することで、シンプルかつ高性能な平均計算が実現できます。時系列データの平滑化や移動平均の算出など、実務でも頻繁に活用されるパターンなので、ぜひ覚えておきましょう。
-
JavaScriptで配列の中央値を計算する方法をわかりやすく解説
中央値(メジアン)とは、数値データを小さい順に並べたときにちょうど中央に位置する値のことです。JavaScriptで配列の中央値を求めるには、まず配列をソートし、その後要素数に応じて処理を分けます。要素数が奇数の場合は中央の1つの要素を、偶数の場合は中央に近い2つの要素の平均値を中央値として返します。中央値の計算手順配列をソートする - 数値配列の場合、sort() メソッドに比較関数 (a, b) => a - b を渡して正しく昇順ソートします。中央のインデックスを求める - Math.floor(arr.length / 2) で中央位置を整数として取得します。要素数の判定を行う
-
JavaScriptで配列の平均値を計算する方法
JavaScriptで配列の平均値を求めるには、配列内のすべての要素を合計し、その合計を配列の長さ(要素数)で割ります。要素の合計を求めるには、forEach()メソッドやreduce()メソッドを使うと簡単に実装できます。コード例<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initia