🎄

ENCA 2日目: Array.prototype.sort 安定化

2024/12/02に公開

安定ソートとは

ソート(並び替え)を実行した際に、順序が等しいものとして扱われる要素の順序が変化しないことが保証されているアルゴリズムを安定ソートと言います。

例えば以下のようなオブジェクトの配列があり、age プロパティでソートする場合に Alice と Charlie の順序が入れ替わらないことが保証されます(昇順、降順問わず必ず Alice の次に Charlie が来る)。

const users = [
  { name: "Alice", age: 30 },
  { name: "Bob", age: 25 },
  { name: "Charlie", age: 30 },
];

有名なアルゴリズムだと挿入ソートやマージソートは安定ソートですが、クイックソートは不安定ソートです。

仕様におけるソート安定化の動き

ECMAScript で定義されている Array.prototype.sort%TypedArray%.prototype.sort はかつて安定性について特に定められておらず、実際に V8 などのいくつかのメジャーな JavaScript エンジンで不安定ソートとなっていました。

自分も過去にこの問題を解決するために、ES Discuss というメーリングリスト[1]で提案したことがあります。

https://esdiscuss.org/topic/stable-sort-proposal

転機が訪れたのは2018年9月のこと。V8 が安定ソートに切り替えたのに呼応して、今まで不安定ソートだったメジャーなエンジンの実装が全て安定ソートに切り替わりました。そして仕様側で sort メソッドの安定を必須化しようと議論され、承認されました。

https://github.com/tc39/ecma262/pull/1340

https://github.com/tc39/ecma262/pull/1433

ES2023 Change Array by Copy の考慮漏れ対応

ES2023 に入った Change Array by Copy の提案によって Array.prototype.toSorted%TypedArray%.prototype.toSorted が追加されました。sort メソッドが配列を破壊的に変更するのに対し、toSorted メソッドは配列をコピーしてから並び替える非破壊的なものとなっています。

るまさんによりこれら toSorted メソッドの安定必須化を明記し忘れられていたことが発見され、報告されました。その後2024年10月の会議で承認され、安定ソートであることが明記されました。

https://x.com/lumc_/status/1833339918342578452

脚注
  1. 今だと TC39 外のユーザーからの提案は Discourse が使われています。 ↩︎

Discussion