何をしたいユーティリティか:「配列の合計算出」
ここでの「合計算出」は、配列の中の値を全部足して、ひとつの数値にまとめる処理です。
一番シンプルなのは「数値配列の合計」ですが、業務では「オブジェクト配列の中の特定の項目の合計」を出したいことがほとんどです。
例えば、こんな場面で使います。
売上リストから「売上金額の合計」を出したい。
請求明細から「数量 × 単価の合計」を出したい。
ログから「処理時間の合計」や「エラー件数の合計」を出したい。
これを毎回 for 文で書くのではなく、「合計算出ユーティリティ」としてまとめておくと、コードがかなり読みやすくなります。
一番基本:数値配列の合計を求める
シンプルなループでの合計
まずは、数値だけが入っている配列の合計です。
function sumNumbers(array) {
if (!Array.isArray(array) || array.length === 0) {
return 0;
}
let total = 0;
for (const value of array) {
if (typeof value !== "number") {
continue;
}
total += value;
}
return total;
}
JavaScriptここで大事なのは、「合計の初期値」と「足し方」です。
total を 0 で始めて、配列の要素を順番に見ながら total += value で足していきます。
数値でないものが混ざっていたらスキップするようにしておくと、変な値が紛れ込んでも壊れにくくなります。
実際の動き
sumNumbers([10, 20, 30]);
// 60
sumNumbers([1, 2, 3, 4, 5]);
// 15
sumNumbers([]);
// 0
sumNumbers([10, "20", 30]);
// 40 ("20" は数値でないのでスキップ)
JavaScript「空配列なら 0 を返す」という仕様にしておくと、呼び出し側で扱いやすくなります。
reduce を使った書き方(中身の意味も理解する)
reduce 版の実装
同じことは Array.prototype.reduce を使っても書けます。
function sumNumbersReduce(array) {
if (!Array.isArray(array) || array.length === 0) {
return 0;
}
return array.reduce((total, value) => {
if (typeof value !== "number") {
return total;
}
return total + value;
}, 0);
}
JavaScriptreduce の第 2 引数の 0 が「合計の初期値」です。
コールバックの total が「今までの合計」、value が「今見ている要素」です。
total + value を返すことで、「前までの合計に今の値を足したもの」が次のループに渡されていきます。
最後まで回ったときの total が、配列全体の合計になります。
「ループで書くとこうなるものを、1 行に圧縮したもの」として理解すると、reduce が怖くなくなります。
オブジェクト配列から「特定の項目の合計」を出す
金額や数量の合計を出したいケース
業務では、次のような配列がよく出てきます。
const items = [
{ id: 1, price: 1000, quantity: 2 },
{ id: 2, price: 500, quantity: 3 },
{ id: 3, price: 2000, quantity: 1 },
];
JavaScriptここから、「price の合計」や「price × quantity の合計」を出したくなります。
まずは「特定のキーの数値を足す」ユーティリティです。
function sumByKeyNumber(array, key) {
if (!Array.isArray(array) || array.length === 0) {
return 0;
}
let total = 0;
for (const item of array) {
if (!item || typeof item !== "object") {
continue;
}
const value = item[key];
if (typeof value !== "number") {
continue;
}
total += value;
}
return total;
}
JavaScriptこの関数は、「指定したキーの値が数値であるものだけ」を対象にして、その合計を返します。
実際の動き
const items = [
{ id: 1, price: 1000, quantity: 2 },
{ id: 2, price: 500, quantity: 3 },
{ id: 3, price: 2000, quantity: 1 },
];
sumByKeyNumber(items, "price");
// 3500
JavaScript「計算した値」の合計を出す(例:金額=単価×数量)
単純なキーでは足りない場合
多くの業務では、「そのままの値」ではなく、「計算した結果」の合計が欲しくなります。
例えば、「price × quantity の合計金額」です。
この場合は、「要素から合計対象の数値を取り出す関数」を渡せるようにすると便利です。
function sumBy(array, valueFn) {
if (!Array.isArray(array) || array.length === 0) {
return 0;
}
let total = 0;
for (const item of array) {
const value = valueFn(item);
if (typeof value !== "number" || Number.isNaN(value)) {
continue;
}
total += value;
}
return total;
}
JavaScriptvalueFn は、「要素を受け取って、その要素から“足したい数値”を返す関数」です。
実際の使い方
単価の合計ならこう書けます。
sumBy(items, (item) => item.price);
// 3500
JavaScript「金額=単価×数量」の合計ならこうです。
sumBy(items, (item) => item.price * item.quantity);
// 1000*2 + 500*3 + 2000*1 = 5500
JavaScriptこのように、「合計対象の値をどう計算するか」を valueFn に閉じ込めておくと、
ユーティリティ側は「それをひたすら足すだけ」で済みます。
実務で意識してほしい設計のポイント
空配列のときは「0」を返すかどうか
合計のときは、空配列なら 0 を返す設計が自然です。
数学的にも「空の和は 0」と考えるのが一般的です。
undefined を返す設計もありえますが、業務コードでは「0 のほうが扱いやすい」ことが多いです。
例えば、「合計金額を表示する」「合計件数をログに出す」といった場面で、undefined より 0 のほうがそのまま使いやすいからです。
なので、合計ユーティリティは、
数値配列の合計 → 空なら 0。
オブジェクト配列の合計 → 対象が一つもなければ 0。
という仕様にしておくと、呼び出し側がシンプルになります。
「数値でないものが混ざったとき」の扱い
現実のデータはきれいとは限らず、"1000" のような文字列や null が紛れ込んでいることもあります。
ここでの方針は大きく 2 つです。
数値でないものは無視して足し続ける。
数値でないものがあったらエラーにする。
ユーティリティとしては「無視して足す」ほうが安全ですが、
「データがおかしいことに気づきたい」場面では、ログを出したり、バリデーションで弾いたりするのも有効です。
少なくとも、「Number(value) で無理やり数値にして足す」のは危険です。Number("abc") が NaN になり、そのまま足すと合計が NaN になってしまうからです。
今回の sumBy では、Number.isNaN(value) をチェックして、
おかしな値はスキップするようにしています。
「合計」と「平均」「最大・最小」はセットで考える
合計を出したら、次に欲しくなるのは「平均」や「最大・最小」です。
例えば、「平均単価」「最大金額」「最小金額」などです。
設計としては、
合計を出すユーティリティ(sumNumbers, sumBy)
件数を数えるユーティリティ
最大・最小を出すユーティリティ
を組み合わせて、「平均」などの指標を作るときれいです。
例えば、平均を出す関数は「合計 ÷ 件数」で書けます。
function averageBy(array, valueFn) {
if (!Array.isArray(array) || array.length === 0) {
return undefined;
}
let total = 0;
let count = 0;
for (const item of array) {
const value = valueFn(item);
if (typeof value !== "number" || Number.isNaN(value)) {
continue;
}
total += value;
count += 1;
}
if (count === 0) {
return undefined;
}
return total / count;
}
JavaScriptこうして、「合計算出ユーティリティ」を軸に、他の集計処理も組み立てていけます。
少し手を動かして感覚をつかむ
コンソールで、次のようなコードを実際に打ってみてください。
sumNumbers([10, 20, 30]);
sumNumbersReduce([10, 20, 30]);
const items = [
{ id: 1, price: 1000, quantity: 2 },
{ id: 2, price: 500, quantity: 3 },
{ id: 3, price: 2000, quantity: 1 },
];
sumByKeyNumber(items, "price");
sumBy(items, (item) => item.price * item.quantity);
JavaScript「どんな値が合計されているか」「空配列のときにどうなるか」を、自分の目で確認してみてください。
そのうえで、自分のプロジェクトに
export function sumNumbers(...) { ... }
export function sumNumbersReduce(...) { ... }
export function sumByKeyNumber(...) { ... }
export function sumBy(...) { ... }
JavaScriptのような関数を置き、
「配列から合計を出したくなったら、必ずこの“合計算出ユーティリティ”を通す」
というルールを作ってみてください。
それだけで、あなたの集計コードは、場当たり的な for 文から、意図と一貫性を備えた業務レベルの実装に近づいていきます。
