数値配列を昇順にソートする

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

数値配列を昇順にソートする とは

Array.prototype.sort に比較関数を渡して、数値配列を正しく昇順・降順に並べる方法を学ぶ。

数値配列を昇順にソートする

JavaScriptArray.prototype.sort は、よく初心者がハマるメソッドの 1 つです。「数値配列をソートしたつもりが、なぜか [10, 2, 33, 4][10, 2, 33, 4] のような並びになってしまう」という経験は誰しもあります。これは sortデフォルトで文字列として比較 するためです。数値を正しく並べるには、必ず 比較関数 を渡します。

ポイント sort の鉄則は 「数値なら必ず比較関数を渡す」。デフォルトは文字列ソートになります。

比較関数なしの罠

まずは罠を体験してみましょう。比較関数を渡さない sort は、要素を 文字列化してから辞書順 で並べます。

JavaScript

const nums = [10, 2, 33, 4]; nums.sort(); console.log(nums); // 文字列比較で意図しない並びになる // "10" は "2" より辞書順では小さい ("1" < "2") ため // [10, 2, 33, 4] が並び替わって [10, 2, 33, 4] のように見える

実際のところ "10""2" よりも辞書順では小さい ("1" < "2") ので、数値の昇順にはなりません。

比較関数で正しく数値ソート

比較関数は 2 引数 (a, b) を受け取り、負の数・0・正の数 を返します。

  • 負の数を返したら ab より前 に並べる
  • 0 を返したら順序維持
  • 正の数を返したら ab より後 に並べる

昇順 (小さい順) なら a - b を返すだけで OK です。

JavaScript

const nums = [10, 2, 33, 4]; const sorted = [...nums].sort((a, b) => a - b); console.log(sorted); // [2, 4, 10, 33]

降順 (大きい順) なら b - a です。

JavaScript

const desc = [...nums].sort((a, b) => b - a); console.log(desc); // [33, 10, 4, 2]

ポイント 「a - b は昇順、b - a は降順」と覚える。マイナスが「前に出す」と読むのがコツです。

sort は破壊的

sort は配列を その場で並び替える破壊的メソッド です。元の配列をそのまま並べ替えてしまいます。

JavaScript

const nums = [3, 1, 2]; const sorted = nums.sort(); console.log(nums === sorted); // true (同じ配列を指している)

元配列を保ちたいときは、先にスプレッドでコピーします。

JavaScript

const nums = [3, 1, 2]; const sorted = [...nums].sort((a, b) => a - b); console.log(nums); // [3, 1, 2] そのまま console.log(sorted); // [1, 2, 3] 新配列

ES2023 以降は toSorted という非破壊版も追加されたので、新しいランタイムなら arr.toSorted((a, b) => a - b) も使えます。

動きを追ってみる

diagram (will load when visible)

sort は要素を比較関数にペアで渡し、戻り値の符号で位置を決めていきます。

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

比較関数の真価はオブジェクト配列で発揮されます。年齢順、価格順、日付順、どれも同じパターンで書けます。

JavaScript

const users = [ { name: "Alice", age: 30 }, { name: "Bob", age: 22 }, ]; users.sort((a, b) => a.age - b.age); console.log(users[0].name); // "Bob"

よくある間違い

第 1 に、sort() を比較関数なしで数値に使うのは前述の通り NG です。第 2 に、sort を呼ぶと元配列が並び替わってしまい、別の場所のコードに影響することがあります。コピーしてからソート が安全です。第 3 に、比較関数で true / false を返すコードを書いてしまう間違いがあります。return a > btrue / false ですが、sort0 / 正 / 負 を期待するので、Safari 等で安定しない動きをします。必ず数値を返す ようにします。

ポイント ソートは「比較関数 + 非破壊コピー」が定石。これだけで予期せぬバグが激減します。

やってみよう

数値配列 arr を受け取り、元配列を変更せずに 昇順ソート済みの新配列を返す sortAsc 関数を書きましょう。return [...arr].sort((a, b) => a - b) の 1 行で完成です。書けたら b - a に変えて降順版を作ったり、users のような配列を age 順に並べる練習もしてみましょう。

よくある質問

Q. ブラウザと Node.js で動作は変わりますか?

A. JavaScript の構文・組み込み機能(配列・文字列・Promise 等)はどちらでも同じです。違いは DOM API(ブラウザ専用)と fs などのファイル系(Node 専用)など、実行環境固有の機能です。コアロジックは両方で動くため、テストもしやすくなります。

Q. ES6 以降の新機能は使っても大丈夫ですか?

A. 現代のブラウザ・Node.js は ES2020 以降の機能をほぼサポートしています。古い IE 等を対象にする必要が無ければ、let/const、アロー関数、分割代入、async/await を積極的に使ってください。トランスパイル(Babel/Vite)が必要なケースは年々減っています。

Q. TypeScript に進む価値はありますか?

A. 型情報があるとリファクタやエディタ補完が劇的に効くため、規模が大きくなるなら TypeScript への移行を強くおすすめします。最初は any を許容しつつ徐々に型を付ければ、JS の知識をそのまま活かせます。

次のレッスン

次は Set で配列の重複を取り除く で、Array.prototype.sort に比較関数を渡して、数値配列を正しく昇順・降順に並べる方法を学ぶ を学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. 数値ソート の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. 数値ソート とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

要件

  1. 比較関数 (a, b) => a - b を sort に渡すこと
  2. 元配列を変更しないこと ([...arr] でコピーしてからソート)
  3. 昇順 (小さい順) で並べること

入出力例

test-cases.txt

sortAsc([10,2,33,4])[2,4,10,33] sortAsc([3,1,2,3,1])[1,1,2,3,3] sortAsc([-1,-10,5,0,2])[-10,-1,0,2,5] sortAsc([])[]

ヒント

main.js
main.js
学習モード

メモ

数値配列を昇順にソートする

⌘S で保存