JavaScript - 配列のソート 同じ値の場合は入れ替わる?

JavaScript の sort() メソッドで配列をソートする場合、 「同じ値」の順番はどうなるのでしょうか?

MDNのマニュアルには「同じ序列を持つ値の順番が保証されません」 と記載されています。

MDN: Array.prototype.sort()

つまり、「入れ替わる場合もあるし、入れ替わらない場合もある」 ということです。

ここでは、「同じ値」を考慮した比較関数の書き方を紹介します。

「同じ値」を考慮しないソート

次のような「名前」と「ポイント」をもつオブジェクトの配列があるとします。

この配列をポイント順(昇順)でソートします。

「同じ値」は考慮していません。「同じ値」の順番が入れ替わるかどうかは不明です


// 名前、得点
var arr = [{name: "田中", point: 80},
		   {name: "山田", point: 90},
		   {name: "鈴木", point: 80},
		   {name: "竹田", point: 60}
		  ];

// ソート
arr.sort(function(a, b){
	if (a.point > b.point){
		return 1;
	} else {
		return -1;
	}
});

console.table(arr);

実行結果は次の通りです。

同じ値を考慮しない

上のコードは、良く見かける比較関数の書き方で、 三項演算子を使って書いている場合もあります。

ただし、この書き方では「同じ値」の順番が入れ替わるかどうかは不明です。

「同じ値」を考慮したソート

次のコードは「同じ値」を考慮した書き方です。

「同じ値」の場合に「return 0;」としているのがポイントです。

「return 0;」とすることで「入れ替えない(順序を変更しない)」ことになります。

ですから、少なくとも「入れ替わるかどうかわからない」という不安がなくなります。

(但し、古いブラウザやマイナーなブラウザでは「return 0;」に対応していない場合があります。)


// 名前、得点
var arr = [{name: "田中", point: 80},
		   {name: "山田", point: 90},
		   {name: "鈴木", point: 80},
		   {name: "竹田", point: 60}
		  ];

// ソート
arr.sort(function(a, b){
	if (a.point > b.point) return 1;
	if (a.point < b.point) return -1;
	return 0;
});

console.table(arr);

実行結果は次の通りです。

同じ値を考慮する

「return 0;」とした場合に、順序を入れ替えない(変更しない)という動作は、 主要なブラウザでは対応しています。

ですから、この書き方の方がおすすめです。

まとめ

sort() メソッドは「同じ値」の順番は保証していません。

同じ場合に「return 0;」とすることで、 順序を入れ替えない(変更しない)ようにすることができます。

主要なブラウザでは「return 0;」のケースに対応しています。