何をしたいユーティリティか:「配列の最小値取得」
ここでの「最小値取得」は、配列の中で一番小さい値を取り出す処理です。
「最大値取得」の逆ですが、業務では同じくらい頻繁に使います。
例えばこんな場面があります。
最も安い価格を知りたい。
最も短い処理時間を知りたい。
最も古い日付(最小のタイムスタンプ)を知りたい。
毎回 for 文を書くのではなく、「最小値取得ユーティリティ」としてまとめておくと、コードが読みやすくなります。
一番基本:数値配列の最小値を取得する
Math.min とスプレッド構文を使う
JavaScript には Math.min という「引数の中で最小の数値を返す」関数があります。
配列をそのまま渡せないので、スプレッド構文を使います。
function minNumber(array) {
if (!Array.isArray(array) || array.length === 0) {
return undefined;
}
return Math.min(...array);
}
JavaScript空配列や配列でないものが来たときは undefined を返すようにしておくと、
「最小値が存在しない」という状態を呼び出し側で判定しやすくなります。
実際の動き
minNumber([10, 5, 30, 7]);
// 5
minNumber([-5, -10, -3]);
// -10
minNumber([]);
// undefined
JavaScriptループで最小値を求める(考え方の基本)
自分で「暫定の最小値」を更新していく
中で何が起きているかを理解するために、ループで書いてみます。
function minNumberLoop(array) {
if (!Array.isArray(array) || array.length === 0) {
return undefined;
}
let min = array[0];
for (let i = 1; i < array.length; i++) {
const value = array[i];
if (value < min) {
min = value;
}
}
return min;
}
JavaScriptやっていることはこうです。
最初の要素を「暫定の最小値」として min に入れる。
2 番目以降の要素を順に見て、「今の min より小さければ min を更新する」。
最後まで見終わったときの min が「配列全体の最小値」になる。
この「暫定値を持っておいて、条件を満たしたら更新する」パターンは、最大値・最小値・合計値などで共通する基本形です。
オブジェクト配列から「特定の項目の最小値」を取る
「最小の値だけ欲しい」場合
業務では、次のような配列がよく出てきます。
const products = [
{ id: 1, price: 1000 },
{ id: 2, price: 500 },
{ id: 3, price: 1500 },
];
JavaScriptここから「price の最小値だけ欲しい」場合のユーティリティです。
function minByKeyNumber(array, key) {
if (!Array.isArray(array) || array.length === 0) {
return undefined;
}
let min = undefined;
for (const item of array) {
if (!item || typeof item !== "object") continue;
const value = item[key];
if (typeof value !== "number") continue;
if (min === undefined || value < min) {
min = value;
}
}
return min;
}
JavaScript数値でないものはスキップし、「数値として比較できるものだけ」の最小値を返します。
実際の動き
const products = [
{ id: 1, price: 1000 },
{ id: 2, price: 500 },
{ id: 3, price: 1500 },
];
minByKeyNumber(products, "price");
// 500
JavaScript「最小値を持つ要素そのもの」を取りたい場合
一番安い商品を丸ごと欲しい
多くの場合、「最小値そのもの」だけでなく、「最小値を持つレコード全体」が欲しくなります。
function minItemByKey(array, key) {
if (!Array.isArray(array) || array.length === 0) {
return undefined;
}
let minItem = undefined;
let minValue = undefined;
for (const item of array) {
if (!item || typeof item !== "object") continue;
const value = item[key];
if (typeof value !== "number") continue;
if (minValue === undefined || value < minValue) {
minValue = value;
minItem = item;
}
}
return minItem;
}
JavaScriptminValue は「今まで見た中での最小の数値」、minItem は「その最小値を持っていたレコード」です。
新しい要素を見たときに、「その値が minValue より小さければ、両方を更新する」という流れです。
実際の動き
const products = [
{ id: 1, price: 1000 },
{ id: 2, price: 500 },
{ id: 3, price: 1500 },
];
minItemByKey(products, "price");
// { id: 2, price: 500 }
JavaScript任意の「評価関数」で最小値を決める
関数で「何を小さいとみなすか」を渡す
キー名ではなく、「要素から評価値を計算する関数」を渡せるようにすると、表現力が上がります。
function minBy(array, scoreFn) {
if (!Array.isArray(array) || array.length === 0) {
return undefined;
}
let bestItem = undefined;
let bestScore = undefined;
for (const item of array) {
const score = scoreFn(item);
if (score == null || Number.isNaN(score)) {
continue;
}
if (bestScore === undefined || score < bestScore) {
bestScore = score;
bestItem = item;
}
}
return bestItem;
}
JavaScriptscoreFn は、「要素を受け取って、その要素の“評価値(スコア)”を返す関数」です。
このスコアが最小の要素を返すユーティリティになります。
実際の使い方
最小価格の商品を取りたいならこう書けます。
const cheapest = minBy(products, (p) => p.price);
// { id: 2, price: 500 }
JavaScript「納期(deliveryDays)が最も短いもの」なども同じです。
const plans = [
{ id: 1, deliveryDays: 7 },
{ id: 2, deliveryDays: 3 },
{ id: 3, deliveryDays: 5 },
];
const fastest = minBy(plans, (p) => p.deliveryDays);
// { id: 2, deliveryDays: 3 }
JavaScript実務で意識してほしい設計のポイント
空配列や「比較対象がない」場合の扱いを決める
Math.min(...[]) は Infinity を返します。
これをそのまま使うと、「最小値が存在しないのに、なぜか Infinity が入っている」という不自然な状態になります。
ユーティリティ側で、
空配列なら undefined を返す。
オブジェクト配列で「数値が一つもなかった」場合も undefined を返す。
と決めておくと、呼び出し側は「undefined なら最小値なし」と判断できて、バグを減らせます。
「値だけ欲しい」と「要素ごと欲しい」を分ける
業務では、
最小値だけ欲しい場面。
最小値を持つレコード全体が欲しい場面。
の両方があります。
関数を分けておくと意図が明確になります。
minNumber → 数値配列の最小値。minByKeyNumber → オブジェクト配列の特定キーの最小値。minItemByKey / minBy → 最小値を持つ要素そのもの。
名前を見ただけで「何が返ってくるか」が分かるようにしておくと、後から読む人にも優しいです。
「比較のルール」をユーティリティに閉じ込める
最小値取得は、「何を基準に小さいとみなすか」という比較ルールとセットです。
単純な数値なら < で十分ですが、
日付文字列や複合的な指標(コスト、納期、リスクなど)を扱う場合は、比較ロジックが少し複雑になります。
そのときに、画面やサービス層のあちこちに比較ロジックを書き散らすのではなく、
minBy のようなユーティリティに「比較の基準(scoreFn)」を集約する。
という設計にしておくと、あとから仕様を変えたいときにも 1 箇所を直すだけで済みます。
少し手を動かして感覚をつかむ
コンソールで、次のようなコードを実際に打ってみてください。
minNumber([10, 5, 30, 7]);
minNumberLoop([10, 5, 30, 7]);
const products = [
{ id: 1, price: 1000 },
{ id: 2, price: 500 },
{ id: 3, price: 1500 },
];
minByKeyNumber(products, "price");
minItemByKey(products, "price");
const plans = [
{ id: 1, deliveryDays: 7 },
{ id: 2, deliveryDays: 3 },
{ id: 3, deliveryDays: 5 },
];
minBy(plans, (p) => p.deliveryDays);
JavaScript「どの値が最小として選ばれているか」「どのレコードが“最小のもの”として返ってきているか」を、自分の目で確認してみてください。
そのうえで、自分のプロジェクトに
export function minNumber(...) { ... }
export function minByKeyNumber(...) { ... }
export function minItemByKey(...) { ... }
export function minBy(...) { ... }
JavaScriptのような関数を置き、
「配列から最小値を取りたくなったら、必ずこの“最小値取得ユーティリティ”を通す」
というルールを作ってみてください。
それだけで、あなたの「最小値を探すコード」は、場当たり的な書き方から、意図と一貫性を備えた業務レベルの実装に変わっていきます。
