JavaScriptのソートとは?配列を並び替える仕組みとsortメソッドの使い方を解説
JavaScriptで一覧データを扱うとき、配列を並び替える処理は非常によく登場します。たとえば、商品一覧を価格の安い順に表示する、ユーザー一覧を名前順に並べる、記事一覧を公開日の新しい順に表示する、ランキングをスコアの高い順に並べるといった機能では、必ずソート処理が関わります。ソートは単にデータの順番を変えるだけの処理に見えますが、実際にはユーザーが情報を探しやすくするための重要な仕組みです。表示順が整理されていない一覧は、目的の情報を見つけにくく、使いにくい画面になってしまいます。
JavaScriptには、配列を並び替えるためのsort()メソッドが標準で用意されています。しかし、sort()は便利な一方で、使い方を誤ると数値が期待通りに並ばなかったり、元の配列が変更されたりすることがあります。特に初心者がつまずきやすいのは、数値配列をそのままsort()したときに、数値の大小ではなく文字列として比較されてしまう点です。本記事では、JavaScriptのソートとは何か、sort()メソッドの基本、比較関数の書き方、数値・文字列・日付・オブジェクト配列の並び替え、実務で注意すべきポイントまで、初心者にも分かりやすく解説します。
1. JavaScriptのソートとは?
JavaScriptのソートとは、配列の要素を指定したルールに従って並び替える処理です。数値を小さい順に並べる、文字列をアルファベット順に並べる、日付を新しい順に並べる、オブジェクト配列を価格やスコアで並べるなど、さまざまな場面で使われます。Webアプリケーションでは、データを取得したあとに画面へ表示する前にソートしたり、ユーザーが選択した条件に応じて表示順を切り替えたりすることがよくあります。
JavaScriptでは、配列に対してArray.prototype.sort()を使うことでソートできます。ただし、sort()は何も指定しなくても動く一方で、常に意図した順番になるとは限りません。比較関数を指定しない場合、要素は基本的に文字列として比較されます。そのため、数値配列を正しく並び替えたい場合や、オブジェクト配列を特定のプロパティで並べたい場合は、比較関数を正しく書く必要があります。ソートを理解するうえでは、単にsort()を使うだけでなく、何を基準に、どの順番で並べるのかを明確にすることが大切です。
1.1 ソートの目的
ソートの目的は、データを見やすく、探しやすく、比較しやすくすることです。たとえば、ユーザーが商品を安い順に確認したい場合、価格順のソートが必要になります。新しく投稿された記事を見たい場合は、公開日の新しい順に並べる必要があります。管理画面では、ユーザー一覧を登録日順に並べたり、注文一覧を金額順に並べたりすることで、必要な情報を素早く確認できます。このように、ソートはデータ表示の品質を高めるために欠かせない処理です。
もしソートが適切に行われていなければ、ユーザーは目的の情報を見つけるために多くの時間を使うことになります。価格順に並んでいるはずの商品一覧で順番がばらばらだったり、新着順のはずの記事一覧で古い記事が上に表示されたりすると、画面全体の信頼性も下がってしまいます。ソートは内部的な配列操作であると同時に、ユーザー体験に直結する機能です。そのため、JavaScriptでWebアプリケーションを作るなら、ソートの基本をしっかり理解しておくことが重要です。
1.2 昇順と降順
昇順とは、小さい値から大きい値へ並べる順序です。数値であれば1, 2, 3のように小さい数字から順番に並び、価格であれば安い順、日付であれば古い日付から新しい日付へ並ぶことが多いです。一方、降順はその逆で、大きい値から小さい値へ並べる順序です。ランキングではスコアの高い順、記事一覧では新しい順、売上一覧では金額の大きい順のように、重要度の高いデータを先に見せたい場合によく使われます。
JavaScriptでは、比較関数の戻り値を変えることで昇順と降順を切り替えます。数値の昇順では(a, b) => a - bを使い、降順では(a, b) => b - aを使います。この書き方を理解しておくと、スコア順、価格順、年齢順、在庫数順など、多くの数値ソートに応用できます。昇順と降順は非常に基本的な概念ですが、実務では表示仕様に応じて頻繁に切り替えるため、比較関数とセットで覚えておくと便利です。
1.3 破壊的メソッドである点
JavaScriptのsort()は、元の配列を直接変更する破壊的メソッドです。つまり、numbers.sort()を実行すると、numbersそのものの順番が変わります。小さなサンプルコードでは問題にならないこともありますが、実務では元の配列をそのまま残しておきたい場面が多くあります。たとえば、検索前の元データを保持したい場合や、複数の並び替え条件を切り替えたい場合、元の配列が変更されると扱いにくくなります。
ReactやVueなどのUIフレームワークで状態管理を行う場合も、元の配列を直接変更することは不具合の原因になりやすいです。状態として管理している配列を直接sort()すると、意図しない再描画やデータの不整合が起きる可能性があります。そのため、元の配列を残したい場合は、スプレッド構文やslice()を使ってコピーを作ってからソートするのが安全です。ソート処理を書くときは、必ず「元の配列を変更してよいのか」を確認する習慣をつけましょう。
const numbers = [3, 1, 2];const sorted = [...numbers].sort((a, b) => a - b);console.log(numbers); // [3, 1, 2]console.log(sorted); // [1, 2, 3]
2. sortメソッドの基本
sort()メソッドは、JavaScriptの配列を並び替えるための標準メソッドです。配列に対して直接呼び出すことができ、文字列配列や数値配列、オブジェクト配列など、さまざまなデータに対して利用できます。ただし、sort()は比較関数を指定するかどうかで動作が大きく変わります。特に数値配列では、比較関数を省略すると期待した並び順にならないことがあるため注意が必要です。
比較関数を理解すると、sort()は非常に柔軟なメソッドになります。単純な数値ソートだけでなく、商品を価格順に並べる、ユーザーを登録日順に並べる、記事をタイトル順に並べる、スコアが同じ場合は名前順に並べるといった複雑な条件にも対応できます。sort()を正しく使うためには、まず比較関数なしの動作を理解し、そのうえで数値の昇順・降順、文字列比較、オブジェクト配列の比較へ進むとよいでしょう。
2.1 比較関数なしのsort
比較関数を指定しない場合、JavaScriptのsort()は配列の要素を文字列として比較します。これは、要素が数値であっても同じです。たとえば、10と2を数値として比べれば2の方が小さいですが、文字列として比べると先頭の文字を基準に比較されるため、10が2より前に来ることがあります。この動作を知らないまま数値配列をsort()すると、結果が正しくないように見える原因になります。
この仕様は、JavaScriptのsort()でよくある初心者のつまずきポイントです。文字列配列を単純にアルファベット順で並べたい場合は比較関数なしでも使えることがありますが、数値配列では基本的に比較関数を指定するべきです。実務では、価格やスコア、数量、年齢、IDなどを扱うことが多いため、数値をソートするときは必ず(a, b) => a - bのような比較関数を書く習慣をつけましょう。
const numbers = [10, 2, 30, 4];numbers.sort();console.log(numbers); // [10, 2, 30, 4] になり得る
2.2 数値を昇順に並べる
数値を昇順に並べるには、比較関数として(a, b) => a - bを指定します。この比較関数では、aがbより小さければ負の値が返り、aが先に配置されます。逆にaがbより大きければ正の値が返り、bが先に配置されます。この仕組みによって、配列全体が小さい値から大きい値へ並び替えられます。数値ソートでは最も基本的で、実務でも頻繁に使う書き方です。
昇順ソートは、価格の安い順、年齢の若い順、数量の少ない順、IDの小さい順など、さまざまな一覧表示で使われます。特にECサイトや管理画面では、ユーザーがデータを比較しやすくするために昇順ソートが必要になることが多いです。sort()の比較関数は一見短いコードですが、戻り値の意味を理解しておくと、ほかのソート条件にも応用しやすくなります。
const numbers = [10, 2, 30, 4];numbers.sort((a, b) => a - b);console.log(numbers); // [2, 4, 10, 30]
2.3 数値を降順に並べる
数値を降順に並べる場合は、比較関数を逆にして(a, b) => b - aと書きます。これにより、大きい値が前に、小さい値が後ろに配置されます。ランキング表示では、スコアやポイントが高い順に見せることが多いため、降順ソートがよく使われます。また、売上金額の高い順、人気数の多い順、在庫数の多い順など、重要な値を上位に表示したい場合にも降順が適しています。
昇順と降順の違いは、比較関数の引き算の向きだけです。a - bなら昇順、b - aなら降順という形で覚えておくと、基本的な数値ソートにはすぐ対応できます。ただし、実務では元の配列を変更したくない場面も多いため、必要に応じてコピーしてからソートすることも忘れないようにしましょう。特に状態管理を行うアプリケーションでは、[...scores].sort((a, b) => b - a)のように書くと安全です。
const scores = [80, 100, 60, 90];scores.sort((a, b) => b - a);console.log(scores); // [100, 90, 80, 60]
3. 文字列と日付のソート
JavaScriptでは、数値だけでなく文字列や日付をソートする場面も多くあります。文字列はユーザー名、商品名、カテゴリ名、タグ名、記事タイトルなどの並び替えに使われます。日付は記事の公開日、注文日時、更新日時、登録日などを基準にした並び替えでよく使われます。これらは数値ソートとは比較方法が異なるため、データの種類に合った書き方を理解しておくことが重要です。
文字列ではlocaleCompare()を使うと、比較意図が分かりやすくなります。日付では、日付文字列をDateオブジェクトやタイムスタンプに変換して比較する方法が一般的です。ただし、日付形式がばらばらだったり、不正な日付文字列が含まれていたりすると、正しくソートできない場合があります。文字列や日付を扱うときは、ソート処理そのものだけでなく、元データの形式が統一されているかも確認する必要があります。
3.1 文字列を並び替える
文字列を自然な順序で並び替えたい場合は、localeCompare()を使うと分かりやすく書けます。localeCompare()は、ある文字列と別の文字列を比較し、並び順を判断するためのメソッドです。単純な英字の名前をアルファベット順に並べる場合だけでなく、ロケールを考慮した比較にも対応できます。ユーザー名や商品名を一覧で表示するときは、文字列比較を明示的に書いた方がコードの意図も伝わりやすくなります。
文字列ソートでは、大文字小文字、日本語、記号、数字を含む文字列など、実際のデータによって並び順が変わることがあります。たとえば、英字だけの配列では問題がなくても、日本語の名前や多言語のデータを扱う場合には、期待した順番にならないことがあります。そのため、ユーザーに表示する重要な一覧では、仕様としてどのような順序にするのかを確認し、必要に応じてlocaleCompare()のロケールやオプションを調整することが大切です。
const names = ["Tanaka", "Aoki", "Sato"];names.sort((a, b) => a.localeCompare(b));console.log(names); // ["Aoki", "Sato", "Tanaka"]
3.2 日付を古い順に並べる
日付を古い順に並べる場合は、比較対象の日付をDateオブジェクトに変換してから比較します。たとえば、記事一覧を公開日の古い順に並べたい場合や、注文履歴を発生順に確認したい場合には、日付の昇順ソートを使います。new Date(a.date) - new Date(b.date)のように書くと、日付が内部的にタイムスタンプとして比較され、古い日付が前に、新しい日付が後ろに配置されます。
ただし、日付ソートでは日付形式の統一が非常に重要です。YYYY-MM-DDのような形式で統一されていれば比較しやすいですが、2024/05/01やMay 1, 2024などが混在していると、環境によって解釈が変わる可能性があります。実務では、APIから受け取る日付形式を統一したり、ソート前に日付として有効かどうかを検証したりすることも大切です。日付は画面表示でよく使われるため、正確な並び替えが求められます。
const posts = [ { title: "A", date: "2024-05-01" }, { title: "B", date: "2024-01-10" }, { title: "C", date: "2024-03-15" }];posts.sort((a, b) => new Date(a.date) - new Date(b.date));console.log(posts);
3.3 日付を新しい順に並べる
日付を新しい順に並べたい場合は、比較を逆にします。つまり、new Date(b.date) - new Date(a.date)のように書きます。この書き方により、新しい日付を持つデータが前に表示されます。ブログ記事一覧、ニュース一覧、通知一覧、注文履歴、チャットメッセージなどでは、新しい情報を先に見せることが多いため、日付の降順ソートは実務で非常によく使われます。
新着順のソートでは、ユーザーが最新情報をすぐに確認できることが重要です。そのため、日付の比較が正しく行われていないと、古い情報が上に表示されたり、最新のデータが埋もれたりしてしまいます。また、タイムゾーンが関係するデータでは、日付だけでなく時刻まで含めて比較する必要がある場合もあります。日付ソートを実装するときは、表示用の形式と比較用の形式を分けて考えると、より安定した処理を書きやすくなります。
posts.sort((a, b) => new Date(b.date) - new Date(a.date));
4. オブジェクト配列のソート
実務では、単純な数値配列や文字列配列よりも、オブジェクト配列をソートする場面の方が多くあります。商品一覧、ユーザー一覧、記事一覧、注文一覧、タスク一覧などは、各要素が複数のプロパティを持つオブジェクトとして表現されることが一般的です。たとえば、商品であればname、price、category、stockなどの情報を持ち、ユーザーであればname、age、createdAtなどの情報を持ちます。
オブジェクト配列をソートする場合は、どのプロパティを基準にするかを明確にする必要があります。価格順にしたいのか、名前順にしたいのか、登録日順にしたいのかによって、比較関数の書き方は変わります。また、同じ値がある場合に別の条件で並べたいこともあります。実務では、単一条件のソートだけでなく、複数条件のソートもよく使われるため、比較関数を整理して書くことが大切です。
4.1 価格順に並べる
商品一覧を価格の安い順に並べる場合は、priceプロパティを比較します。products.sort((a, b) => a.price - b.price)のように書くことで、価格が小さい商品から順番に並び替えられます。この処理は、ECサイトや商品管理画面で非常によく使われます。ユーザーが「安い順」を選択したときや、管理者が低価格の商品から確認したいときに役立ちます。
価格順ソートは数値ソートの応用です。ただし、実務ではpriceが必ず数値で入っているとは限りません。APIやCSVから取得したデータでは、価格が文字列として入っていることもあります。その場合、数値に変換してから比較しないと、正しい順序にならない可能性があります。また、価格が未設定の商品がある場合は、それを先頭に出すのか末尾に出すのかといった仕様も決めておく必要があります。
const products = [ { name: "Keyboard", price: 5000 }, { name: "Mouse", price: 2000 }, { name: "Monitor", price: 20000 }];products.sort((a, b) => a.price - b.price);console.log(products);
4.2 名前順に並べる
オブジェクト配列を名前順に並べる場合は、文字列比較を使います。商品名やユーザー名、カテゴリ名などを基準に並べるときは、localeCompare()を使うと読みやすくなります。たとえば、products.sort((a, b) => a.name.localeCompare(b.name))のように書けば、nameプロパティを基準にして並び替えられます。比較対象が文字列であることが明確になるため、コードの意図も伝わりやすくなります。
名前順ソートでは、データの表記揺れにも注意が必要です。大文字小文字が混在している場合や、英語と日本語が混在している場合、期待した順序にならないことがあります。また、名前が空文字だったり、nameプロパティ自体が存在しないデータが含まれていたりすると、エラーや不安定なソート結果につながる可能性があります。実務では、必要に応じてデフォルト値を用意したり、ソート前にデータを整えたりすると安全です。
products.sort((a, b) => a.name.localeCompare(b.name));
4.3 複数条件で並べる
実務では、1つの条件だけではなく、複数の条件で並べたい場面があります。たとえば、商品をカテゴリ順に並べ、同じカテゴリの中では価格の安い順に並べるようなケースです。この場合、まずカテゴリを比較し、カテゴリが異なる場合はその結果を返します。カテゴリが同じ場合だけ、次の条件として価格を比較します。このように、比較関数の中で優先順位を明確にすることで、複数条件のソートを実装できます。
複数条件のソートでは、条件が増えるほど比較関数が複雑になりやすいです。そのため、実務では比較処理を別関数に切り出したり、ソート条件を分かりやすくコメントで補足したりすることが大切です。また、categoryが存在しない場合や、priceが数値でない場合など、データの欠損にも対応できるようにしておくと安全です。複数条件のソートは一覧表示の品質に大きく関わるため、仕様に沿って丁寧に実装しましょう。
products.sort((a, b) => { const categoryCompare = a.category?.localeCompare(b.category ?? "") ?? 0; if (categoryCompare !== 0) { return categoryCompare; } return a.price - b.price;});
5. JavaScriptソートの注意点
JavaScriptのソートは便利ですが、いくつか注意すべきポイントがあります。特に重要なのは、比較関数を省略しないこと、sort()が元の配列を変更すること、比較対象のデータ形式をそろえることです。これらを理解せずにソート処理を書くと、見た目には動いているように見えても、特定のデータで不具合が発生する可能性があります。たとえば、数値が文字列として比較されたり、日付が正しく解釈されなかったり、オブジェクトのプロパティが存在せずエラーになったりすることがあります。
実務では、ソート処理を関数化し、いくつかのテストケースを用意しておくと安全です。特に一覧画面では、表示順がユーザー体験に直結します。価格順、名前順、新着順、ランキング順など、ユーザーが期待する順序になっているかを確認することが大切です。また、空データ、同じ値を持つデータ、欠損値を含むデータなどもテストしておくと、実際の運用で問題が起きにくくなります。
5.1 元配列の変更に注意する
sort()は元の配列を直接変更します。これは、JavaScriptのソート処理で最も重要な注意点の一つです。元データを保持したい場合は、必ずコピーしてからソートする必要があります。たとえば、const sorted = [...items].sort(...)のように書けば、元のitems配列は変更されません。検索結果やフィルター結果を複数の条件で並べ替える場合にも、元データを壊さない設計が役立ちます。
ReactやVueなどで状態管理を行っている場合、元配列の直接変更は特に注意が必要です。状態を直接変更すると、変更検知がうまく働かなかったり、意図しない表示更新が発生したりすることがあります。ソートは見た目の順番を変えるだけの処理に見えますが、元データに影響する可能性があるため、破壊的メソッドであることを常に意識しましょう。安全に扱うためには、コピーしてから並び替える習慣をつけることが大切です。
5.2 比較対象を明確にする
オブジェクト配列をソートするときは、どのプロパティを比較するのかを明確にする必要があります。priceを基準にするのか、createdAtを基準にするのか、nameを基準にするのかによって、比較関数の書き方は変わります。比較対象が曖昧なままコードを書くと、後から読んだときに意図が分かりにくくなります。実務では、ソート条件が仕様として決まっていることが多いため、その仕様に沿って比較対象を明示することが重要です。
また、比較対象のプロパティが存在しない場合の扱いも考えておく必要があります。たとえば、ある商品だけpriceが未設定だったり、あるユーザーだけnameが空だったりすることがあります。そのようなデータが含まれていると、ソート結果が不安定になったり、エラーが発生したりする可能性があります。比較関数の中でデフォルト値を使う、ソート前にデータを整形する、欠損値の表示位置を仕様として決めるなど、安定した処理にする工夫が必要です。
5.3 データ形式を統一する
ソート処理では、データ形式の統一が非常に重要です。数値として比較したい値が文字列として入っている場合、期待した順序にならないことがあります。日付も同様で、形式が統一されていないと正しく比較できない場合があります。たとえば、2024-05-01と05/01/2024のような形式が混在していると、環境や解釈によって結果が変わる可能性があります。ソート前にデータ形式を整えることは、安定した並び替えのための基本です。
実務では、APIから受け取ったデータをそのままソートするのではなく、必要に応じて型変換やバリデーションを行うことが大切です。価格は数値に変換する、日付は比較しやすい形式に統一する、文字列は空文字やnullを考慮するなど、データの状態を確認してからソートすると安全です。ソート結果が不自然な場合、比較関数だけでなく元データの形式に原因があることも多いため、データ形式の確認を習慣にしましょう。
おわりに
JavaScriptのソートは、配列データを見やすく並び替えるための基本処理です。標準のArray.prototype.sort()を使えば簡単に実装できますが、比較関数を正しく指定しないと期待した結果にならないことがあります。特に数値配列では、比較関数を省略すると文字列として比較されるため、(a, b) => a - bや(a, b) => b - aのような書き方を覚えておくことが重要です。
文字列、日付、オブジェクト配列など、データの種類によって比較方法は変わります。価格順、名前順、新着順、ランキング順など、実務でよく使うパターンを練習しておくと、さまざまな画面実装に対応しやすくなります。また、sort()は元の配列を変更する破壊的メソッドであるため、必要に応じてコピーしてから使うことも大切です。JavaScriptのソートを正しく理解することで、一覧表示、検索結果、ランキング、管理画面などの品質を高めることができます。
EN
JP
KR