配列sortを考える(javascript)

JavaScript

デフォルトのArray.prototype.sort()は地味な罠があるので覚書。

数字の配列をそのままsort()

ダメです。compareFunctionを指定しないsort()は文字列比較を行います。
なので[2, -5, -1].sort()のようなことをやると、
[-1, -5, 2]という変な配列になります。

数字の配列を正しく並び替えるには下のような比較関数を使います。

const arr = [2,-5,-1];

arr.sort(function(a,b){
  if(a > b) {
    return -1;
  }
  if(a < b) {
    return 1;
  }
  return 0;
});

または

arr.sort((a, b) => a - b);

文字種混合した配列のsort

文字種の混合とは大文字/小文字のアルファベットだったり、ひらがな/カタカナが混在するようなときのソートです。
通常のsort()を利用する場合以外に、Intl.Collator()やlocalCompare()があります。
Intl.Collator()やlocalCompare()は対象となる言語を指定することで、その言語に沿った並び替えを行えます。(なお2つはほぼ同様の動きをしますが、Intl.Collatorの方が動作が早いようです。)

で、通常のsort()とIntl.Collator()を使うと何が違うかを具体的に見てみましょう。

const hoge = ['アあ', 'Ga', 'A', 11, 111, '123', '1', '1a', 'ああ', '26', 5, 'a', 'ab', 'dd', 'カ', 'CA', '伊', 1, 'EE', 'カ', 'か', 'さ', 'アイ', 3, 'ア', 'gg', 'サ', 'ア', '2', 'サ', '亜', 'アア', 'あ', '宇'];

hoge.sort();
console.log(hoge);
-> ["1", 1, 11, 111, "123", "1a", "2", "26", 3, 5, "A", "CA", "EE", "Ga", "a", "ab", "dd", "gg", "あ", "ああ", "か", "さ", "ア", "アあ", "アア", "アイ", "カ", "サ", "亜", "伊", "宇", "ア", "カ", "サ"]

hoge.sort(new Intl.Collator('ja').compare);
console.log(hoge);
->["1", 1, 11, 111, "123", "1a", "2", "26", 3, 5, "a", "A", "ab", "CA", "dd", "EE", "Ga", "gg", "あ", "ア", "ア", "ああ", "アあ", "アア", "アイ", "か", "カ", "カ", "さ", "サ", "サ", "亜", "伊", "宇"]

sort()

数字、大文字、小文字、ひらがな、カタカナ、漢字、半角カナ
という順で大まかな並び順が決まります。
先頭文字の種別で別れてしまうため「か」のあとに「ア」が来てしまうわけです。

Intl.Collator()

数字、アルファベット、かな、漢字
という順で並んでいます。
ひらがな・カタカナ・半角カナの違いは区別されていませんね。
こちらの方が日本語的には読み仮名順な感じでなじみやすいのではないでしょうか?

コメント