Pythonのsorted()関数は安定していることが保証されていますか?


95

ドキュメントには、これを保証するものではありません。文書化されている他の場所はありますか?

リストの並べ替えメソッドは安定していることが保証されており(Note 9th point: "Python 2.3以降、sort()メソッドは安定していることが保証されています")、並べ替えは機能的に似ているので、私はそれが安定していると思います。しかし、そのように言う決定的な情報源を見つけることはできません。

目的:両方のレコードで主キーが等しい場合、主キーと副キーに基づいてソートする必要があります。sort()が安定していることが保証されている場合は、2次キーでソートしてから、1次キーでソートして、必要な結果を得ることができます。

PS:混乱を避けるために、「等しい要素の相対的な順序を変更しないことが保証されている場合、ソートは安定している」という意味で、stableを使用しています。

回答:


126

はい、マニュアルの意図は確かにそれsortedが安定していることを保証することであり、実際にそれがsortメソッドとまったく同じアルゴリズムを使用することです。私はドキュメントがこのアイデンティティについて100%明確ではないことを理解しています。docパッチは常に喜んで受け入れられます!


2
タプルまたはリストをソートする場合、「プライマリ」ソートキーが等しい場合は常に、「セカンダリ」キーでソートされることがわかりました。たとえば、元の入力を同じシーケンス/順序でsorted([(1, 2), (1, 1)])返すのでは[(1, 1), (1, 2)]なく、戻ります。安定性の保証は、元の[(1, 2), (1, 1)]入力を返すことを意味するのではないですか?その場合、あなたは明確に言って言うべきですsorted([(1, 2), (1, 1)], key=lambda t: t[0])
code_dredd

10
これは、この場合に予想されることではありませんか?Pythonは、最初の「プライマリ」要素だけでなく、デフォルトですべての要素を通じてタプルを比較します。最初の要素のみでソートする場合は、keyパラメーターを明示的に渡すことができます。
Matias Grioni 2017年

2
@code_dreddこれは予想される動作です。安定ソートのポイントは「ソートキー」を使用したソートですが、同じソートキーを持つ2つの異なる要素は同じ順序になります。タプルのデフォルトのソートキーは、タプルのすべての要素です。
guyarad

27

彼らは安定しています。

ちなみに、マルチパスソートとシングルパスソートを組み合わせることで、ソートとソートが安定しているかどうかを知ることができない場合があります。

ソートしたい場合たとえば、自分に基づいてオブジェクトlast_namefirst_name属性、あなたは1回のパスでそれを行うことができます。

sorted_list= sorted(
    your_sequence_of_items,
    key= lambda item: (item.last_name, item.first_name))

タプル比較を利用します。

この回答は現状のままで、元の質問をカバーしています。並べ替えに関するその他の質問については、Python Sorting How-Toを参照してください


4
ソートを逆にしたい場合、これは望ましくない影響を与える可能性があります。たとえば、製品を並べ替える場合、最初に評価(昇順)で並べ替え、次に価格(昇順)で並べ替えることができます。これを逆にすると、評価は降順でソートされ、価格は昇順でソートされます。これはこのソリューションでは機能しません。
Remco Wendt、2012年

2
@RemcoWendt:あなたが説明することに対する要件はありませんでした。いずれの場合も、引数の代わりにを検討key= lambda item: (-item.rating, item.price)または指定してください。ただし、コメントの目的はまだわかりません。cmpkey
tzot

1
確かにそれは要件ではありませんでしたが、他の人がこれを読んで、ソリューションとPythonの安定したソート機能のどちらを使用するかを選択するときに、この微妙な違いを指摘したかったのです。
Remco Wendt

そうですか。言い換えると、パフォーマンスを気にしない限り、ペアによるソートの方が明確であるため、望ましい方法です。違いは無視できるかもしれませんが、2つの安定した並べ替えは、ペアによる1つの並べ替えよりもいくらか速いと思います。
osa

8
@tzot言いたいのですが、安定したソートには常にそのような要件があります。たとえば、タプル(レート、コメント)のリストがあり、コメントは作成された順に保存されます。レートで並べ替え、時間の順序を維持したいのですが、リスト内のタイムスタンプ。簡単に言うと、リストをレートで並べ替えて、コメントを同じ順序に保ちます。
wsysuper 2015

3

その間に変更されたドキュメント(関連するcommit)と現在のドキュメントでは、sortedそれが明示的に保証されています。

組み込みsorted()関数は安定していることが保証されています。等しいと比較する要素の相対的な順序を変更しないことが保証されている場合、並べ替えは安定しています。これは、複数のパスで並べ替える場合に便利です(たとえば、部門で並べ替えてから、給与等級で並べ替えます)。

どのようドキュメントのこの部分は、(+)のPython 2.7とPython 3.4に追加されたに準拠し、その言語のバージョンの実装が必要があります持っている安定しましたsorted

CPythonの場合、Python 2.3list.sort以降安定しています。

  • Tim Petersが彼のlist.sort()実装を書き直しました-これは「安定したソート」(同じ入力が同じ順序で出力に現れる)であり、以前よりも高速です。

私は100%確信が持てませんがsorted、最近では簡単に使用できますlist.sortていますが、その履歴を確認していません。ただし、「常に」使用されている可能性がありlist.sortます。


0

「新機能」のPython 2.4用ドキュメント)効果(ソートされたポイントを作ることは最初のリストを作成し、その後、あなたは「公式」ドキュメントではないが必要な保証をご提供し、その上)(ソートを呼び出します。本当に心配な場合は、ソースを確認することもできます。


1
それがそう言うところを指さしていただけませんか?それは、sorted()が「インプレースlist.sort()のように機能し」、「新しく形成されたコピーがソートされる」と言いますが、内部的にsort()を使用しているとはわかりません。
sundar-モニカを

形成される「コピー」はリスト(戻り値として取得するもの)であり、戻る前にそのリストで.sort()が呼び出されます。QED。いいえ、それは難攻不落の証拠ではありませんが、Pythonが公式の標準を持つまでは、それを得ることができません。
Peter Hansen、

0

並べ替えに関するPython 3.6のドキュメントでは、

ソートは安定していることが保証されています

さらに、そのドキュメントには、安定したTimsortへのリンクがあります。

Timsortはバージョン2.3以降、Pythonの標準のソートアルゴリズムです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.