🐣

[JavaScript] 最も優しいArray.prototype.sort()メソッドの数値並び替え解説

2020/10/23に公開

この記事を書くに至った経緯

こんにちは、ドイツでフリーランスのフルスタックエンジニアをしています、Arisaです。

教材販売と、個別プログラミング学習サポートを提供する、「オーダーメイド感覚プログラミング学習サービス | Lilac(ライレック)」を開発しています。

個別プログラミング学習サポートは、2018年から教えています。

40名以上マンツーマンで教え、国内、海外の企業にweb系エンジニアとして就職した卒業生や、フリーランスのエンジニアとして成功した卒業生もいます。

プログラミングを教えてきた経験から、公式ドキュメントや上級者向けのチュートリアルでは割愛されがちな内容も、細かく解説をしながら伝えることを大切にしています。

今回は、JavaScript学習者から難しいという感想が多い、 sort() メソッドについて、最も優しい解説をしていきたいと思います。

この記事の目的: 公式ドキュメント、MDNを読んでもわからなかったことをクリアにする

MDNはとても信頼性の高いソースで、何か新しい技法を学習するときや、基本構文を見直したい時によく使用する人が多いものです。

でも、プログラミング初心者にとっては、読んでもよくわからず、何となく真似をして構文を書いて動いた、でも技法自体の構文の構成などはよくわからない、で終わってしまうことが多いのです。

公式ドキュメントだけでは理解が難しいプログラミング学習者に、

「公式ドキュメントを読んだらわかりますよ」

と、突き放したくないので、MDNを読んでもいまいち理解ができなかった、消化不良な気がする、という人向けに、MDNに書いてある内容の、最も優しい解説をします。

この記事の対象者

まず、MDNの解説をざっと読んで、 sort() メソッドについて、人に説明できるのであれば、この記事は読まなくてもしっかり理解ができています。

MDN: Array.prototype.sort()

説明ができるまでではない、ということであれば、以下の解説を読み進めていきます。

まずは何が何でも基本構文

sort() メソッドの基本構文を、今のところは読んで理解ができなくても、構造をMDNで見て確認します。

arr.sort([compareFunction]);

MDNには、このように構文が書いてありますね。

数値をソートしたい場合

そして、少し先に、 「文字列の代わりに数字を比較する場合、比較関数は単純に a から b を引けばよいでしょう。」 と書いてあり、MDNの例のコードを見ると

function compareNumbers(a, b) {
  return a - b;
}

と、まずは sort() メソッドを使わない、最もシンプルな関数宣言の形で、ソート、つまり順番を並び替える方法を書いています。

ソートする単位があることを知ろう

この sort() メソッドで引数として入る関数は 比較関数 と呼ばれる役割の関数で、他の関数と何ら変わりはありません。

ですが、 コンピューターが利用できるデータに変更をするルール で、 UTF-16という単位 があるんですね。

UTF-8と同じ部類のもので、こちらはマークアップ言語である、HTMLやCSSを書いたことのある方は、お目にかかったことがあると思います。

この、 コンピューターが利用できるデータに変更をするルールのUTF-16という単位 を基準にして、 sort() メソッドの順番並び替えは行われています。

比較関数の引数a - bの処理フローを見よう

この順番づけのルールに基づくと、上記の比較関数にある引数a - bで何が起こるかというと、以下の3つのパターンが起こると、決められています。

  1. a - b が 0 未満の場合: a を b より小さい順番で順番づけをする(つまり、a が先に来る)
  2. a - b が 0 の場合、a と b は互いに変更せず、他の要素に対して1や3のケースに当てはまる場合、1や3のルールに従って順番づけしていく
  3. a - b が 0以上の場合、b を a 順番で順番づけをする(つまり、b が先に来る)

つまり、この順番のルールは決まっているものなので、それに従って順番が決まるということになります。

そのことを踏まえて、上記の例に sort() メソッドを組み合わせたMDNの1つの例を見ると、

// ※ MDNは変数宣言にvarを使用していますが、この記事ではES6を取り扱うため、letに直しています
let numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
  return a - b;
});
console.log(numbers);
// [1, 2, 3, 4, 5]

と、結果が返ります。

上記で何が起こっているかを具体的に処理のフローを書くと

  1. 配列numbersの値の中身は [4, 2, 5, 1, 3] の順
  2. 引数aにまず4が入り、引数bに2が入る → 4 - 2 = 2になる
  3. 上記の順番並び替えルールで言う、ケース3に当てはまるので、b → a の順番になる → 2, 4の順になる
  4. 残りの数値の繰り返し → 1, 2, 3, 4, 5の順になる

ということがわかります。

応用の仕方

今回sortメソッドでソートさせたい値は、文字列では無く、数値なので、もし、この記事を読んでいる方で、何かソートしたい値が数値であれば、上記の例を、ほぼそっくりそのまま使えるということになります。

なので、上記の例にそのままソートしたい値を書き換えれば、基本的には、原理もしっかり理解した上でソートができてしまいます。

まとめ

いかがでしたか?

MDNを読め、と言われて読んだはいいけど、よくわからず、何となく sort() メソッドを使っている、という状況から打破できたでしょうか?

このように、きちんと基本構文の構造さえ丁寧に「何がどうしてそうなるのか」ということを1つずつ見ていくと、きちんと原理を理解して、応用することができるようになります。

プログラミング学習中の方に、少しでもお役に立てる記事なっていれば幸いです。

参考: MDN、Array.protptype.sort() https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

参考: Qiita、「新人さんに知ってほしい「文字コードのお話」」 https://qiita.com/yuji38kwmt/items/b3a7820b4d3b544da4ff

今後の学習の参考

教材販売と、個別プログラミング学習サポートを提供する、「オーダーメイド感覚プログラミング学習サービス | Lilac(ライレック)」 では、一般的にはチュートリアルなどでも割愛されがちな内容まで、丁寧に解説をすることを心がけた教材も、先行販売しています。

既に先行販売している教材は、Zennのこのプラットフォームより、私のZennプロフィールからご確認いただけます。

フロントエンド開発の教材(マークアップ言語、webサイト公開手順、実践で使われるGithubの使い方、JavaScript(ES6)、React.js、React Native、Gatsby.js)を、随時、完成したものから販売をしていきます。

1つのトピックに対して1冊の本(各2,000円)、という短い読み切りのボリュームで、全ての本は、半分無料公開中です。

練習問題も答えを含め、一部無料公開しています。

Lilacの教材をもとに、個別プログラミング学習サポートもご希望の方は、こちらからご連絡ください。

個別学習サポートに含まれるコンテンツと料金

料金: 8,000円/週

サポートコンテンツ

  • テキスト教材
  • 週1回 30分〜1時間の通話面談
  • 無制限チャットサポート(24時間以内返信。頻度の目安: 1日1, 2回)
  • 無制限コードレビュー(同上)
  • フリーランス向け: 案件受注、納品サポート
  • 企業就職希望向け: 企業面接対策

Discussion