【JavaScript】配列を自在に並べ替える!sortメソッドと昇順・降順の完全理解

目次

概要

配列データの「並べ替え(ソート)」は、ランキング表示やリスト整理において必須の機能です。

JavaScriptの sort メソッドは非常に強力ですが、「デフォルトでは文字列として比較される」という独特な仕様を持っており、数値のソートでハマりやすいポイントでもあります。本記事では、比較関数を使った正しい数値ソート(昇順・降順)の実装方法と、破壊的変更への対策について解説します。

仕様(入出力)

sort メソッド

配列の要素を並べ替えます。

引数説明戻り値
compareFn (省略可)ソート順序を定義する関数。
(a, b) => 数値 の形式で記述。
・戻り値が の場合: ab より前に配置
・戻り値が の場合: ba より前に配置
0 の場合: 変更なし
並べ替えられた配列そのもの
(元の配列への参照)
  • 副作用: 元の配列の中身が変更されます(破壊的メソッド)。
  • 注意: 引数を省略すると、全要素を文字列に変換してから辞書順(Unicode順)で比較します(例: 102 より先に来る)。

基本の使い方

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') を使用すると、日本語環境に適した辞書順ソートが可能になります。

注意点

  1. 破壊的メソッドであるsortreverse と同様に、元の配列を直接書き換えます。元の順序を保持したい場合は、[...examResults].sort(...) のようにコピーを作成してからソートするか、新しい非破壊的メソッド toSorted() を使用してください。
  2. デフォルトの挙動(辞書順)比較関数を渡さない 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点を抑えておけば、意図しない並び順になるトラブルを防ぐことができます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次