JavaScript
ECMAScript

JavaScriptのsortについて理解を深める


はじめに

JavaScriptのsortメソッドが直感的に少しわかりにくいと感じたので、アウトプットしておきたいと思います。


sortメソッドの注意点

sortメソッドは破壊的メソッドということに注意が必要です。

これを間違えるとバグを引き起こしてしまう原因になってしまう可能性があります。


実際に見てみる

sortメソッドはデフォルトではUnicodeコードポイント(文字列比較)の昇順にソートされます。みてみましょう。

const months = ['March', 'Jan', 'Feb', 'Dec'];

months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]

const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]

上のコードのarray1のように数字の場合でも、数的なソートではなく文字列比較に基づきソートされることに注意が必要です。

そして、ちょっと理解しずらいのが引数にcallback functionをとる場合です。

MDNのドキュメントでは、以下のようにcallback functionの引数がaとbで書いてあり少しわかりずらいと個人的に思いました。

function compare(a, b) {

if (ある順序の基準において a b より小) {
return -1;
}
if (その順序の基準において a b より大) {
return 1;
}
// a は b と等しいはず
return 0;
}

実際にはa→previous value, b→current valueを表しているので、これからa→pre, b→curと書いていくことで理解を深めたいと思います。

最初の要素からArray.prototype.reduceのように一つづつずらしていくイメージです。

重要↓

そして、以下の3パターンのみ覚えればJavaScriptのsortはマスターできます!

1. callback functionが0未満を返す場合、pre を cur より小さい添字にソートする。

2. callback functionが0を返す場合、pre と cur は変化しない。

3. callback functionが0より大きい値を返す場合、cur を pre より小さい添字にソートする。

これを、具体例で見て行きます。

const items = [

{ name: 'Edward', value: 21 },
{ name: 'Sharpe', value: 37 },
{ name: 'And', value: 45 },
{ name: 'The', value: -12 },
{ name: 'Magnetic', value: 13 },
{ name: 'Zeros', value: 37 }
];

// 名前順にソート
items.sort((pre, cur) => {
const nameA = pre.name.toUpperCase(); // 大文字と小文字を無視する
const nameB = cur.name.toUpperCase(); // 大文字と小文字を無視する
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}

// names must be equal
return 0;
});

このように書くことができます。慣習的に0未満の値には-1, 0より大きい値には1を用います。


補足

単に数字を比較する場合はもっと単純に次のようにも書くこともできます。(これも上の理論と原理は一緒です。)

const numbers = [4, 2, 5, 1, 3];

numbers.sort((pre, cur) => {
return pre - cur;
});
console.log(numbers);

// [1, 2, 3, 4, 5]

この書き方も覚えておくと良いと思います!

最後まで読んでいただきありがとうございました!