JavaScript配列のソート(数値)の基本と実践
数値配列を正しく並べ替えるには、比較関数を渡して「数値として」比較させるのがポイントです。デフォルトのsortは文字列として比較するため、数値だと期待通りの順序になりません。
構文と考え方
// 昇順(小さい→大きい)
arr.sort((a, b) => a - b);
// 降順(大きい→小さい)
arr.sort((a, b) => b - a);
JavaScript- 比較関数: 返り値が0未満ならaが先、0なら同順、0より大ならbが先。
- 破壊的変更: sortは元の配列を書き換えます。元を残したい場合はコピーしてから。
const sorted = [...arr].sort((a, b) => a - b); // 安全(元は保持)
JavaScriptすぐ使えるテンプレート集
基本の昇順・降順
const nums = [1, 2, 10, 3, 5];
// 昇順
nums.sort((a, b) => a - b);
console.log(nums); // [1, 2, 3, 5, 10]
// 降順
nums.sort((a, b) => b - a);
console.log(nums); // [10, 5, 3, 2, 1]
JavaScript- ポイント: 文字列比較の落とし穴([1, 2, 10] → [1, 10, 2])を避けるために、必ず比較関数を渡す。
価格や年齢など「数値のキー」で並べる
const products = [
{ name: "Pen", price: 120 },
{ name: "Note", price: 300 },
{ name: "Bag", price: 450 },
];
// 価格の昇順
products.sort((a, b) => a.price - b.price);
console.log(products.map(p => p.name)); // ["Pen", "Note", "Bag"]
// 価格の降順
products.sort((a, b) => b.price - a.price);
console.log(products.map(p => p.name)); // ["Bag", "Note", "Pen"]
JavaScript- ポイント: 比較する「数値キー」を明示する。
複合条件(まず数値、同値なら文字列)
const items = [
{ name: "Banana", qty: 2 },
{ name: "Apple", qty: 2 },
{ name: "Orange", qty: 5 },
];
// qtyの昇順、qtyが同じなら名前の辞書順
items.sort((a, b) => {
const d = a.qty - b.qty;
return d !== 0 ? d : a.name.localeCompare(b.name);
});
console.log(items.map(i => `${i.qty}-${i.name}`)); // ["2-Apple","2-Banana","5-Orange"]
JavaScript- ポイント: 返り値を段階的に決める。文字列比較にはlocaleCompareが便利。
未定義・空値を末尾に送る(安全な比較)
const nums = [10, undefined, 3, null, 7];
nums.sort((a, b) => {
const ax = Number.isFinite(a) ? a : Infinity; // 非数値は末尾へ
const bx = Number.isFinite(b) ? b : Infinity;
return ax - bx;
});
console.log(nums); // [3, 7, 10, undefined, null]
JavaScript- ポイント: 異常値の扱いを先に決めておくとバグを防げる。
よくある落とし穴と対策
- 文字列として並ぶ問題: 比較関数を渡さないと文字列比較になる。数値は必ず
(a, b) => a - bを使う。 - 元配列が書き換わる: sortは破壊的。元を保持したいならスプレッドでコピーしてからsort。
- NaNや非数値の混在: 比較で想定外の順序に。事前にフィルタするか、比較関数で扱いを定義。
- 多言語文字列の並び: 文字列キーでソートする場合は
localeCompareを使うと直感的な辞書順になりやすい。
目的別の使い分け
- 単純な数値昇順/降順:
(a, b) => a - b/(a, b) => b - a - 数値キー(price、ageなど):
(a, b) => a.key - b.key - 複合条件(数値→文字列): 先に数値比較、同値なら
localeCompare - 元を保持:
const sorted = [...arr].sort(...)
練習問題(手を動かして覚える)
1. 数値配列を昇順に
const nums = [9, 1, 4, 1, 5];
console.log([...nums].sort((a, b) => a - b)); // [1, 1, 4, 5, 9]
JavaScript2. 年齢の降順でユーザーを並べ替え
const users = [
{ name: "Aki", age: 19 },
{ name: "Mao", age: 22 },
{ name: "Ren", age: 17 },
];
console.log([...users].sort((a, b) => b.age - a.age).map(u => u.name)); // ["Mao","Aki","Ren"]
JavaScript3. 点数の昇順、同点は名前の辞書順
const scores = [
{ name: "Banana", score: 80 },
{ name: "Apple", score: 80 },
{ name: "Orange", score: 90 },
];
const sorted = [...scores].sort((a, b) => {
const d = a.score - b.score;
return d !== 0 ? d : a.name.localeCompare(b.name);
});
console.log(sorted.map(s => `${s.score}-${s.name}`)); // ["80-Apple","80-Banana","90-Orange"]
JavaScript直感的な指針
- 数値なら必ず比較関数を渡す。
- 元を壊したくないならコピーしてからsort。
- 複合条件は「優先キー→次キー」の順で返り値を決める。
