【JavaScript】オブジェクト配列の並べ替え!特定のプロパティを基準にソートする方法

目次

概要

実務における「ソート(並べ替え)」のほとんどは、単純な数値や文字列の配列ではなく、データベースから取得した「オブジェクトの配列(JSONデータ)」を対象とします。

本記事では、オブジェクト内の特定のプロパティ(IDや名前、日付など)を基準にして、配列全体の順序を並べ替える実装パターンを解説します。

仕様(入出力)

オブジェクト配列のソートロジック

sort メソッドの引数である比較関数 (a, b) の中で、比較したいプロパティ同士 を取り出して計算します。

比較対象コード例(昇順)解説
数値プロパティ(a, b) => a.id - b.id引き算の結果(負・0・正)を利用します。
文字列プロパティ(a, b) => a.name.localeCompare(b.name)localeCompare メソッドで辞書順比較を行います。
  • 入力: オブジェクトを含む配列
  • 出力: 特定のキーで並べ替えられた配列(破壊的変更)

基本の使い方

ID(数値)でソートする場合

オブジェクト ab から、比較したい id プロパティを取り出して引き算します。

const users = [
    { id: 3, name: 'Tree' },
    { id: 1, name: 'Forest' }
];

// IDの昇順(小さい順)
users.sort((a, b) => a.id - b.id);

console.log(users); 
// [{ id: 1, name: 'Forest' }, { id: 3, name: 'Tree' }]

コード全文(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>Employee Directory Sort</title>
    <style>
        .directory-container {
            font-family: 'Hiragino Kaku Gothic ProN', sans-serif;
            max-width: 600px;
            margin: 20px auto;
            border: 1px solid #ccc;
            border-radius: 8px;
            padding: 20px;
            background-color: #fcfcfc;
        }
        .controls {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 1px solid #eee;
        }
        button {
            padding: 10px 15px;
            cursor: pointer;
            border: 1px solid #007bff;
            background-color: #fff;
            color: #007bff;
            border-radius: 4px;
            font-weight: bold;
        }
        button:hover, button.active {
            background-color: #007bff;
            color: #fff;
        }
        table {
            width: 100%;
            border-collapse: collapse;
        }
        th, td {
            text-align: left;
            padding: 10px;
            border-bottom: 1px solid #ddd;
        }
        th { background-color: #f0f0f0; color: #333; }
        .id-col { width: 80px; text-align: center; }
        .kana-col { color: #666; font-size: 0.85em; }
    </style>
</head>
<body>

<div class="directory-container">
    <h3>社員名簿一覧</h3>
    
    <div class="controls">
        <button id="sort-id">社員番号順 (1, 2...)</button>
        <button id="sort-kana">フリガナ順 (あいう...)</button>
        <button id="sort-desc">社員番号 降順 (9, 8...)</button>
    </div>

    <table>
        <thead>
            <tr>
                <th class="id-col">ID</th>
                <th>氏名</th>
                <th>フリガナ</th>
            </tr>
        </thead>
        <tbody id="employee-list">
            </tbody>
    </table>
</div>

<script src="directory_sort.js"></script>
</body>
</html>

JavaScript

/**
 * 社員名簿ソートスクリプト
 * オブジェクト配列のソートロジック実装
 */

// 1. 社員データ(オブジェクトの配列)
const employees = [
    { id: 104, name: '中林', kana: 'ナカバヤシ' },
    { id: 101, name: '森',   kana: 'モリ' },
    { id: 103, name: '小林', kana: 'コバヤシ' },
    { id: 108, name: '大木', kana: 'オオキ' },
    { id: 102, name: '小木', kana: 'オギ' },
    { id: 105, name: '大森', kana: 'オオモリ' }
];

// DOM要素
const tbody = document.getElementById('employee-list');
const btnSortId = document.getElementById('sort-id');
const btnSortKana = document.getElementById('sort-kana');
const btnSortDesc = document.getElementById('sort-desc');

/**
 * テーブルを描画する関数
 */
const renderTable = () => {
    tbody.innerHTML = '';
    
    employees.forEach(emp => {
        const tr = document.createElement('tr');
        tr.innerHTML = `
            <td class="id-col">${emp.id}</td>
            <td>${emp.name}</td>
            <td class="kana-col">${emp.kana}</td>
        `;
        tbody.appendChild(tr);
    });
};

/**
 * IDで昇順ソート (数値比較)
 */
const sortById = () => {
    employees.sort((a, b) => a.id - b.id);
    updateActiveButton(btnSortId);
    renderTable();
};

/**
 * IDで降順ソート (数値比較)
 */
const sortByIdDesc = () => {
    employees.sort((a, b) => b.id - a.id);
    updateActiveButton(btnSortDesc);
    renderTable();
};

/**
 * フリガナで昇順ソート (文字列比較)
 */
const sortByKana = () => {
    employees.sort((a, b) => {
        // localeCompareを使用して日本語の辞書順比較を行う
        return a.kana.localeCompare(b.kana, 'ja');
    });
    updateActiveButton(btnSortKana);
    renderTable();
};

/**
 * ボタンの見た目を更新するヘルパー関数
 */
const updateActiveButton = (activeBtn) => {
    // 全ボタンのactiveクラスを削除
    [btnSortId, btnSortKana, btnSortDesc].forEach(btn => btn.classList.remove('active'));
    // 押されたボタンにactiveクラスを付与
    activeBtn.classList.add('active');
};

// 初期表示
renderTable();

// イベントリスナー
btnSortId.addEventListener('click', sortById);
btnSortKana.addEventListener('click', sortByKana);
btnSortDesc.addEventListener('click', sortByIdDesc);

カスタムポイント

  • 日本語(漢字)のソート:漢字の名前(例: 「森」と「林」)を直接ソートしようとすると、文字コード順になり、期待する「あいうえお順」にはなりません。必ずフリガナのプロパティ(kana)を持たせて、それを基準に localeCompare することをお勧めします。
  • 日付のソート:Date オブジェクトを持つプロパティの場合は、a.date.getTime() - b.date.getTime() のように数値(タイムスタンプ)に変換してから引き算します。

注意点

  1. プロパティの存在保証比較するプロパティ(例: a.kana)が undefinednull の場合、エラーになったり予期せぬ順序になったりします。データに欠損がある可能性がある場合は、空文字に置換するなどのガード処理が必要です。const valA = a.kana || '';
  2. 文字列と数値の混同IDが文字列の "101" と数値の 102 で混在していると正しくソートできません。必ず型を統一するか、比較関数内で Number(a.id) のように変換してください。

応用

複合ソート(多重ソート)

「部署コード順」に並べ、同じ部署の中では「役職順」に並べる、といった実装です。

employees.sort((a, b) => {
    // 1. まず部署コードで比較
    if (a.deptId !== b.deptId) {
        return a.deptId - b.deptId;
    }
    
    // 2. 部署が同じなら、役職ランクで比較(数値が小さいほど偉いとする)
    return a.rank - b.rank;
});

まとめ

オブジェクト配列のソートは、比較関数 (a, b) => ... の書き方次第で自由にコントロールできます。

  • 数値なら a.prop - b.prop
  • 文字列なら a.prop.localeCompare(b.prop)

この2つのパターンを基本とし、必要に応じて複合条件を組み込むことで、あらゆる業務データの並べ替えに対応できます。

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

この記事を書いた人

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

目次