目次
概要
配列データの「並べ替え(ソート)」は、ランキング表示やリスト整理において必須の機能です。
JavaScriptの sort メソッドは非常に強力ですが、「デフォルトでは文字列として比較される」という独特な仕様を持っており、数値のソートでハマりやすいポイントでもあります。本記事では、比較関数を使った正しい数値ソート(昇順・降順)の実装方法と、破壊的変更への対策について解説します。
仕様(入出力)
sort メソッド
配列の要素を並べ替えます。
| 引数 | 説明 | 戻り値 |
compareFn (省略可) | ソート順序を定義する関数。(a, b) => 数値 の形式で記述。・戻り値が 負 の場合: a を b より前に配置・戻り値が 正 の場合: b を a より前に配置・0 の場合: 変更なし | 並べ替えられた配列そのもの (元の配列への参照) |
- 副作用: 元の配列の中身が変更されます(破壊的メソッド)。
- 注意: 引数を省略すると、全要素を文字列に変換してから辞書順(Unicode順)で比較します(例:
10は2より先に来る)。
基本の使い方
1. 数値を昇順(小さい順)にする
比較関数で a - b を返します。
a が小さいとき結果が負になり、a が前に来ます。
const scores = [80, 5, 100];
scores.sort((a, b) => a - b);
console.log(scores); // [5, 80, 100]
2. 数値を降順(大きい順)にする
比較関数で b - a を返します。
b が大きい(aより大きい)とき結果が正になり、b が前に来ます(入れ替わる)。
const scores = [80, 5, 100];
scores.sort((a, b) => b - a);
console.log(scores); // [100, 80, 5]
コード全文(HTML / JavaScript)
社内試験の成績リストを管理するシステムです。
「点数の高い順(降順)」や「低い順(昇順)」に並べ替える機能を実装します。
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Exam Score Ranking</title>
<style>
.ranking-board {
font-family: 'Helvetica Neue', Arial, sans-serif;
max-width: 500px;
margin: 20px auto;
border: 2px solid #333;
border-radius: 8px;
background-color: #fff;
padding: 20px;
}
.controls {
display: flex;
gap: 10px;
margin-bottom: 20px;
justify-content: center;
}
button {
padding: 10px 20px;
cursor: pointer;
border: none;
border-radius: 4px;
font-weight: bold;
color: white;
}
.btn-asc { background-color: #4CAF50; }
.btn-desc { background-color: #f44336; }
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 12px;
border-bottom: 1px solid #ddd;
text-align: left;
}
th { background-color: #f2f2f2; }
.score-col { text-align: right; font-weight: bold; }
</style>
</head>
<body>
<div class="ranking-board">
<h3 style="text-align:center;">社内試験 成績一覧</h3>
<div class="controls">
<button id="sort-desc" class="btn-desc">降順 (高い順)</button>
<button id="sort-asc" class="btn-asc">昇順 (低い順)</button>
</div>
<table>
<thead>
<tr>
<th>氏名</th>
<th class="score-col">点数</th>
</tr>
</thead>
<tbody id="score-list">
</tbody>
</table>
</div>
<script src="ranking.js"></script>
</body>
</html>
JavaScript
/**
* 成績ランキング管理スクリプト
* sortメソッドによる並べ替え処理
*/
// 1. 成績データ(オブジェクトの配列)
// 順不同のデータ
const examResults = [
{ name: '森', score: 78 },
{ name: '小林', score: 92 },
{ name: '中木', score: 65 },
{ name: '大林', score: 88 },
{ name: '林', score: 78 },
{ name: '大森', score: 100 },
{ name: '小木', score: 45 }
];
// DOM要素
const listBody = document.getElementById('score-list');
const btnAsc = document.getElementById('sort-asc');
const btnDesc = document.getElementById('sort-desc');
/**
* リストを描画する関数
*/
const renderTable = () => {
listBody.innerHTML = '';
examResults.forEach((data) => {
const tr = document.createElement('tr');
tr.innerHTML = `
<td>${data.name}</td>
<td class="score-col">${data.score}点</td>
`;
listBody.appendChild(tr);
});
};
/**
* 昇順ソート(低い順)
* 比較関数: a - b
*/
const sortAscending = () => {
examResults.sort((a, b) => {
// オブジェクトのscoreプロパティ同士を比較
return a.score - b.score;
});
renderTable();
};
/**
* 降順ソート(高い順)
* 比較関数: b - a
*/
const sortDescending = () => {
examResults.sort((a, b) => {
// 条件分岐で書く場合の例(これでもOKですが b - a の方が簡潔です)
if (a.score < b.score) return 1; // aが小さいなら後ろへ
if (a.score > b.score) return -1; // aが大きいなら前へ
return 0;
});
renderTable();
};
// 初期表示
renderTable();
// イベント設定
btnAsc.addEventListener('click', sortAscending);
btnDesc.addEventListener('click', sortDescending);
カスタムポイント
- 比較関数の簡略化:コード内の
sortDescending関数ではif文を使っていますが、数値比較であればreturn b.score - a.score;の一行だけで同じ動作になります。 - 日本語ソート:名前(文字列)でソートしたい場合、単純な比較演算子では期待通りにならないことがあります。
a.name.localeCompare(b.name, 'ja')を使用すると、日本語環境に適した辞書順ソートが可能になります。
注意点
- 破壊的メソッドである
sortはreverseと同様に、元の配列を直接書き換えます。元の順序を保持したい場合は、[...examResults].sort(...)のようにコピーを作成してからソートするか、新しい非破壊的メソッドtoSorted()を使用してください。 - デフォルトの挙動(辞書順)比較関数を渡さない
array.sort()は、数値を文字列に変換して比較します。このため、[10, 2, 5]をソートすると[10, 2, 5](”10″は”2″より文字コード的に先)という直感に反する結果になります。数値ソートには必ず比較関数が必要です。
応用
複数条件でのソート(SQLのORDER BY相当)
「点数が同じなら、名前順に並べる」といった複合ソートの実装例です。
examResults.sort((a, b) => {
// 1. 点数で比較(降順)
if (a.score !== b.score) {
return b.score - a.score;
}
// 2. 点数が同じなら名前で比較(昇順)
// localeCompareは文字列比較用のメソッド
return a.name.localeCompare(b.name, 'ja');
});
まとめ
配列の並べ替えは、データの可視化において不可欠な処理です。
- 数値ソート: 必ず
(a, b) => a - b(昇順)またはb - a(降順)を指定する。 - 副作用: 元の配列が書き換わることを意識する。
この2点を抑えておけば、意図しない並び順になるトラブルを防ぐことができます。
