JavaScriptのソートを少し理解したときの話

JavaScriptのsort()

ソート自体はsort()を使えばできるというのは知ってはいました。

const numbers = [1, 9, 3, 8, 2, 6];
numbers.sort();
console.log(numbers); // [1, 2, 3, 6, 8, 9]

とすればこうなるというのは、なんとなく妥当な気がしていましたし、何の文句もありませんでした。

ソートしろと言われたら、まずはこう書いてしまうのではないかという感じの書き方です。

ただし、このコードだと意図しない挙動になる可能性があるのですが、それについては後述します。

理解できなかったコード

最初にどこで見かけたのかは忘れましたが、はじめに見たときは「ナニコレ」以外の感想が無かったような気がします。

const numbers = [1, 9, 3, 8, 2, 6];
numbers.sort((a, b) => a - b);
console.log(numbers); // [1, 2, 3, 6, 8, 9]

このコードの挙動としては、上のように最初のコードと同じ結果になりますが、どうしてこうなるのか意味不明でした。

sort()の使い方

Array.prototype.sort() - JavaScript | MDNを見れば書いてあることですが、sort()には比較関数という、並べ方を決めるための関数を渡すことができます。

そして、この比較関数に2つ引数を与えてなんらかの計算をして、その結果が0と比べて大きいのか小さいのか、はたまた同じなのかというのを見てソートされます。

const numbers = [1, 9, 3, 8, 2, 6];
numbers.sort((a, b) => a - b);
console.log(numbers); // [1, 2, 3, 6, 8, 9]

ここで、このコードについてもう一度見てみると、a, b2つの引数をとり、関数の返り値がa - bなので、この結果をもとに並べ替えられます。

今回はa-bが0未満の場合、つまり、a < b ならば aが先に来て、a - b が0より大きい場合、つまり、b < a ならば bが先に来るというように並べ替えられます。

ということは、全体として見ると小さいものから先に並べられるということになるので、昇順に並べ替えられます。

ここで、比較関数を変えれば結果が変わるので、降順にしたいときには比較関数を逆にするだけで降順になります。

const numbers = [1, 9, 3, 8, 2, 6];
numbers.sort((a, b) => b - a); // a - b から b - aに変更
console.log(numbers); // [9, 8, 6, 3, 2, 1]

というように変更すると、降順に並べ替えられるというわけです。

結局、比較関数有りがいいのか

ここまでで、昇順に並べ替えたいなら比較関数とか入れなくていいじゃんと思ってしまうのですが、そうはいかないらしいです。

最初にも書いたように、比較関数を入れないと意図しない挙動になることがあります。

というのも、Array.prototype.sort() - JavaScript | MDNにこれまた書いてあるのですが、比較関数が与えられない場合、undefined以外の配列の要素は全て文字列に変換されてからソートされるそうなのです。

これによって考えられる挙動の一例として、以下のようなものがあります。

const numbers = [1, 9, 3, 8, 2, 6, 10, 38];
numbers.sort();
console.log(numbers); // [1, 10, 2, 3, 38, 6, 8, 9]

最初のコードと違う点としては、2桁の数値を配列に入れているという点です。

前述の通り、比較関数を使用しないと配列の要素が文字列に変換されてから並べ替えられるので、上のような結果になってしまいます。

このような結果は、ほとんどの場合では意図しない結果じゃないかなと思います。

const numbers = [1, 9, 3, 8, 2, 6, 10, 38];
numbers.sort((a, b) => a - b);
console.log(numbers); // [1, 2, 3, 6, 8, 9, 10, 38]

このように比較関数を使うことで、意図しない挙動を防ぐことができると思うので、なるべく比較関数を使うようにするのが良いのではないかなぁと思います。

参考

Array.prototype.sort() - JavaScript | MDN

管理人 : tecchan

プログラミング初心者なのでいろいろ勉強してます。なんでもできるようになる予定。目標は年収5億円。好きなものは公園と図書館とラーメン。頭よくなりたいです。

詳しくはAbout