Array.prototype.sort()メソッドの基本的な使い方10選

JavaScriptのArray.prototype.sortメソッドを使った配列のソートJS
この記事は約13分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●Array.prototype.sortメソッドとは?

JavaScriptの配列を扱う上で、Array.prototype.sortメソッドは非常に重要な役割を果たします。

このメソッドを使えば、数値や文字列の配列を簡単に並べ替えることができるのです。

例えば、商品の価格を安い順に表示したいとき、ユーザーの名前をアルファベット順に並べたいとき、あるいはゲームのスコアを高い順に表示したいとき。

こういったシーンでArray.prototype.sortメソッドが大活躍します。

sortメソッドは配列自体を直接変更し、並べ替えられた配列を返します。

つまり、元の配列の順序が変更されるということですね。

ただ、そのまま使うと思わぬ結果になることがあるので、正しく使いこなすためにはいくつかポイントを押さえておく必要があります。

○sortメソッドの基本的な使い方

では早速、sortメソッドの基本的な使い方を見ていきましょう。

sortメソッドは、引数なしで呼び出すと、配列の要素を文字列に変換した上で、UTF-16コード単位の値の順序で並べ替えを行います。

つまりデフォルトでは、数値も文字列として扱われるということですね。

次のサンプルコードを見てみましょう。

○サンプルコード1:デフォルトのソート

const arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
arr.sort();
console.log(arr);

実行結果

[1, 1, 2, 3, 3, 4, 5, 5, 6, 9]

数値の配列に対してsortメソッドを呼び出すと、期待通りの結果が得られました。

数字が昇順に並べ替えられていますね。

でも、次の例はどうでしょうか。

const arr = [1, 30, 4, 21, 100000];
arr.sort();
console.log(arr);

実行結果

[1, 100000, 21, 30, 4]

数値としては正しくソートされていないようです。

これは、先ほど述べたように、デフォルトでは要素を文字列として扱うためです。

文字列の「1」、「2」、「3」、「4」の順になっているのがわかりますね。

数値をきちんと並べ替えるには、sortメソッドに比較関数を渡す必要があります。

○サンプルコード2:数値のソート

const arr = [1, 30, 4, 21, 100000];
arr.sort((a, b) => a - b);
console.log(arr);

実行結果

[1, 4, 21, 30, 100000]

比較関数(a, b) => a - bを渡すことで、数値が正しい順序でソートされました。

この比較関数は、2つの要素abを受け取り、a - bの結果が負ならaを先に、正ならbを先に並べるという意味です。

○サンプルコード3:文字列のソート

文字列の配列も、デフォルトのsortメソッドで並べ替えることができます。

const arr = ['banana', 'cherry', 'apple'];
arr.sort();
console.log(arr);

実行結果

['apple', 'banana', 'cherry']

アルファベット順に並べ替えられていますね。

ただ、このデフォルトの動作はUTF-16コード単位の値に基づいているので、常に期待通りの結果が得られるわけではありません。

例えば、アクセント記号付きの文字を含む場合や、大文字と小文字が混在する場合などです。

こういったケースでは、適切な比較関数を用意する必要があります。

localeCompareメソッドを使うのも一つの方法ですね。

●ソート順のカスタマイズ

デフォルトのソート順が期待通りにならないケースは意外と多いものです。

例えば、数値の配列を並べ替えるときに文字列として扱われてしまったり、大文字と小文字が混在する文字列の配列で思わぬ結果になったり。

Array.prototype.sortメソッドには、ソート順をカスタマイズする方法がちゃんと用意されているんです。

○サンプルコード4:昇順と降順の切り替え

ソートのデフォルトは昇順ですが、降順に並べ替えたい場合もありますよね。

そんな時は、比較関数を工夫することで簡単に切り替えられます。

const arr = [1, 30, 4, 21, 100000];

// 昇順ソート
arr.sort((a, b) => a - b);
console.log(arr);

// 降順ソート
arr.sort((a, b) => b - a);
console.log(arr);

実行結果

[1, 4, 21, 30, 100000]
[100000, 30, 21, 4, 1]

比較関数でa - bとすれば昇順、b - aとすれば降順になるわけです。

これは、比較関数が正の値を返せばbを先に、負の値を返せばaを先に並べるという仕組みを利用しています。

○サンプルコード5:独自の比較関数の使用

比較関数を自分で定義すれば、より複雑なソート順のルールを実現できます。

例えば、文字列の長さを基準に並べ替えるなんてことも可能です。

const arr = ['apple', 'banana', 'cherry', 'date'];

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

実行結果

['date', 'apple', 'banana', 'cherry']

比較関数で各文字列の長さを比べることで、文字列の長さ順にソートされました。

○サンプルコード6:オブジェクトのソート

配列の要素がオブジェクトだった場合、特定のプロパティを基準にソートしたいということもあるでしょう。

const arr = [
  { name: 'John', age: 30 },
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 35 }
];

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

実行結果

[
  { name: 'Alice', age: 25 },
  { name: 'John', age: 30 },
  { name: 'Bob', age: 35 }
]

比較関数の中で、オブジェクトのageプロパティを比較することで、年齢順にソートができました。

同じ要領で、他のプロパティを基準にソートすることも可能ですね。

比較関数を使いこなせば、ソート順のカスタマイズは思いのままです。

配列の要素の型に合わせて適切な比較方法を選ぶことが大切ですね。

●よくあるエラーと対処法

Array.prototype.sortメソッドを使っていると、時々思わぬエラーに遭遇することがあります。

初心者の頃は特に、エラーメッセージを見てもどこが悪いのかわからなくて困ってしまうものです。

ここでは、sortメソッドを使う際によく出くわすエラーとその対処法を見ていきましょう。

エラーの原因を理解して、正しくソートを行えるようになりましょう。

○”TypeError: arr.sort is not a function”

このエラーは、sortメソッドを呼び出そうとしているオブジェクトが配列ではない場合に発生します。

例えば、次のようなコードではエラーが起きてしまいます。

const notAnArray = 'hello';
notAnArray.sort();

実行結果

TypeError: notAnArray.sort is not a function

文字列の'hello'は配列ではないので、sortメソッドを持っていません。

エラーを避けるには、sortメソッドを呼び出す前に、対象が本当に配列であるかを確認する必要があります。

Array.isArray()メソッドを使うのが一般的ですね。

const notAnArray = 'hello';
if (Array.isArray(notAnArray)) {
  notAnArray.sort();
}

こうすれば、配列ではないオブジェクトに対してsortメソッドを呼び出すことはなくなります。

○比較関数が正しく動作しない

比較関数の書き方を間違えると、期待通りのソート結果が得られないことがあります。

例えば、数値の配列を昇順にソートするつもりで、次のような比較関数を書いたとします。

const arr = [1, 30, 4, 21, 100000];
arr.sort((a, b) => {
  if (a < b) {
    return -1;
  }
  if (a > b) {
    return 1;
  }
});
console.log(arr);

実行結果

[1, 100000, 21, 30, 4]

期待した昇順になっていません。

比較関数の戻り値は、負の値、0、正の値のいずれかである必要があります。

この例では、abが等しい場合の戻り値を指定していないため、正しくソートできていないのです。

比較関数は、abより小さい場合は負の値、等しい場合は0、大きい場合は正の値を返すように書きましょう。

const arr = [1, 30, 4, 21, 100000];
arr.sort((a, b) => {
  if (a < b) {
    return -1;
  }
  if (a > b) {
    return 1;
  }
  return 0;
});
console.log(arr);

実行結果

[1, 4, 21, 30, 100000]

これで正しくソートされました。

比較関数の仕様をしっかり理解して、適切な戻り値を返すようにしましょう。

○ソート結果が予期しない順序になる

文字列の配列をソートする際、大文字と小文字が混在していると予期しない順序になることがあります。

const arr = ['apple', 'Banana', 'cherry', 'Date'];
arr.sort();
console.log(arr);

実行結果

['Banana', 'Date', 'apple', 'cherry']

デフォルトのソートでは、大文字が小文字よりも先に来てしまいます。

これを避けるには、比較関数の中で大文字と小文字を区別しないように処理を行う必要があります。

localeCompare()メソッドを使うのが簡単です。

const arr = ['apple', 'Banana', 'cherry', 'Date'];
arr.sort((a, b) => a.localeCompare(b));
console.log(arr);

実行結果

['apple', 'Banana', 'cherry', 'Date']

localeCompare()メソッドは、文字列を言語に依存した方法で比較し、適切な順序で並べ替えてくれます。

●sortメソッドの応用例

さて、ここまでArray.prototype.sortメソッドの基本的な使い方やカスタマイズ方法を見てきましたが、実際の開発現場ではもっと様々な場面でソートを活用しています。

ちょっとややこしいですが、sortメソッドを使った応用例をいくつか見ていきましょう。

きっと、配列操作の幅が広がるはずです。

○サンプルコード7:重複要素の削除

配列から重複する要素を取り除きたい場合、ソートを活用することができます。

まず配列をソートし、隣り合う要素を比較していくことで、重複をスキップできるのです。

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

arr.sort();
const uniqueArr = arr.filter((val, i, self) => {
  return i === 0 || val !== self[i - 1];
});

console.log(uniqueArr);

実行結果

[1, 2, 3, 4, 5]

ソートした後、filter()メソッドを使って隣り合う要素を比較しています。

先頭の要素(i === 0)と、1つ前の要素と異なる場合だけtrueを返すようにすれば、重複が取り除かれた配列が得られます。

○サンプルコード8:ランダムな順序へのシャッフル

配列の要素をランダムな順序に並び替えたい場合は、Math.random()を使った比較関数を利用できます。

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

arr.sort(() => Math.random() - 0.5);

console.log(arr);

実行結果(例)

[3, 1, 4, 2, 5]

Math.random() - 0.5は、-0.5から0.5の範囲の値をランダムに返します。

これを比較関数として使うことで、要素がランダムに並び替えられます。

○サンプルコード9:複数のプロパティを用いたソート

オブジェクトの配列を複数のプロパティに基づいてソートしたい場合は、比較関数の中で条件分岐を使います。

const arr = [
  { name: 'John', age: 30, city: 'New York' },
  { name: 'Alice', age: 25, city: 'London' },
  { name: 'Bob', age: 30, city: 'Paris' },
  { name: 'Mary', age: 25, city: 'New York' },
];

arr.sort((a, b) => {
  if (a.age !== b.age) {
    return a.age - b.age;
  } else {
    return a.city.localeCompare(b.city);
  }
});

console.log(arr);

実行結果

[
  { name: 'Mary', age: 25, city: 'New York' },
  { name: 'Alice', age: 25, city: 'London' },
  { name: 'Bob', age: 30, city: 'Paris' },
  { name: 'John', age: 30, city: 'New York' }
]

まずはageプロパティで昇順にソートし、ageが同じ場合はcityプロパティでソートしています。

cityの比較にはlocaleCompare()メソッドを使っていますね。

○サンプルコード10:日本語の文字列のソート

日本語の文字列を配列にソートする場合、localeCompare()メソッドに適切なロケールを指定する必要があります。

const arr = ['ゆり', 'あさがお', 'ひまわり', 'さくら'];

arr.sort((a, b) => a.localeCompare(b, 'ja'));

console.log(arr);

実行結果

['あさがお', 'さくら', 'ひまわり', 'ゆり']

localeCompare()メソッドの第2引数に'ja'を指定することで、日本語に適した方法で文字列を比較し、正しい順序で並べ替えることができます。

まとめ

JavaScriptのArray.prototype.sortメソッドは、配列のソートを行う強力な機能です。

デフォルトの動作をよく理解し、比較関数を適切に使いこなすことが大切です。

ソートに関連するエラーへの対処法を身につけることで、より安定したコードを書けるようになるでしょう。

また、応用的な使い方を知ることで、柔軟な配列操作が可能となります。

sortメソッドをマスターすれば、配列データを自在に扱えるようになります。

基本をしっかりと押さえつつ、徐々に応用範囲を広げていきましょう。