Python'un sort () işlevinin kararlı olması garanti ediliyor mu?


101

Dokümantasyon garanti etmez. Belgelendiği başka bir yer var mı?

Listelerdeki sıralama yönteminin kararlı olması garanti edildiğinden (Notlar 9. nokta: "Python 2.3 ile başlayarak sort () yönteminin kararlı olması garanti edilir") ve sıralamanın işlevsel olarak benzer olması nedeniyle kararlı olabileceğini tahmin ediyorum . Ancak, bunu söyleyen kesin bir kaynak bulamıyorum.

Amaç: Her iki kayıtta da birincil anahtarın eşit olduğu durumlarda birincil anahtara ve ayrıca ikincil anahtara göre sıralama yapmam gerekiyor. Sıralı () 'nın kararlı olması garanti edilirse, ikincil anahtara göre sıralayabilirim, ardından birincil anahtara göre sıralayabilir ve ihtiyacım olan sonucu alabilirim.

Not: Herhangi bir karışıklığı önlemek için, "eşit karşılaştırılan öğelerin göreceli sırasını değiştirmemeyi garanti ediyorsa bir sıralama kararlıdır" anlamında kararlı kullanıyorum.

Yanıtlar:


131

Evet, kılavuzun amacı gerçekten sortedde kararlı olduğunu ve aslında sortyöntemle tamamen aynı algoritmayı kullandığını garanti etmektir . Dokümanların bu kimlik konusunda% 100 net olmadığının farkındayım; doc yamaları her zaman memnuniyetle kabul edilir!


2
Demetleri veya listeleri sıralıyorsam, "birincil" sıralama anahtarları eşit olduğunda, "ikincil" anahtarla sıralamanın sona erdiğini buldum. Örneğin , orijinal girdiyi aynı sıra / sırada sorted([(1, 2), (1, 1)])döndürmek [(1, 1), (1, 2)]yerine döndürür . Kararlılık garantisi, orijinal [(1, 2), (1, 1)]girdiyi geri getirmesi gerektiği anlamına gelmemeli mi? Bu durumda, açık olmalı ve şunu söylemelisinizsorted([(1, 2), (1, 1)], key=lambda t: t[0])
code_dredd

10
Bu durumda beklenen bu değil mi? Python, sadece ilk "birincil" olanı değil, öntanımlı olarak tuple'ları tüm öğelerle karşılaştıracaktır. Yalnızca ilk öğeye göre sıralamak istiyorsanız, keyparametreyi açıkça iletebilirsiniz .
Matias Grioni

2
@code_dredd bu beklenen davranıştır. Kararlı sıralamanın amacı, bir "sıralama anahtarı" kullanarak sıralamadır, ancak aynı sıralama anahtarına sahip iki farklı öğe aynı sırada olacaktır. Bir demet için varsayılan sıralama anahtarı, başlığın tüm öğeleridir.
guyarad

29

Bunlar kararlı .

Bu arada: Çok geçişli sıralamayı tek geçişte birleştirerek sıralamanın ve sıralamanın kararlı olup olmadığını bazen göz ardı edebilirsiniz.

Bu sıralamada istiyorsanız Örneğin, onların objelerin last_name, first_namenitelikler, bir geçişte yapabilirsiniz:

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

demet karşılaştırmasından yararlanarak.

Bu cevap, olduğu gibi, orijinal soruyu kapsar. Sıralama ile ilgili diğer sorular için Python Sıralama Nasıl Yapılır .


5
Sıralamayı tersine çevirmek isterseniz, bu istenmeyen bir etkiye neden olabilir. Örneğin, ürünleri sıralarken, önce derecelendirmeye (artan sıra) ve ardından fiyata (ayrıca artan) göre sıralamak isteyebilirsiniz. Bunu tersine çevirirseniz, derecelendirmeye göre azalan sırada, ancak artan sırada fiyata göre sıralamak istersiniz. Bu, bu çözümle çalışmaz.
Remco Wendt

2
@ RemcoWendt: Tarif ettiğiniz şey için herhangi bir gereklilik yoktu. Her durumda, bir argüman yerine key= lambda item: (-item.rating, item.price)a'yı düşünün veya sağlayın . Yine de yorumunuzun amacından emin değilim. cmpkey
tzot

1
Aslında bu bir gereklilik değildi, ancak diğer insanlar bunu okuduğunda ve çözümünüz veya Python'un kararlı sıralama özelliğini kullanmak arasında bir seçim yaptığında bu ince farkı belirtmek istediler.
Remco Wendt

Anlıyorum. Başka bir deyişle, çiftlere göre sıralama daha nettir ve bu nedenle performansı önemsemediğiniz sürece tercih edilir. Farkın ihmal edilebilir olmasına rağmen, iki kararlı türün çiftler halinde bir sıralamadan biraz daha hızlı olduğunu hayal ediyorum -?
Sergey Orshanskiy

8
@tzot Bahsetmek istiyorum, kararlı sıralama için her zaman böyle gereksinimler vardır. Örneğin, bir demet listem var (oran, yorum), yorumlar yapıldıkları sıraya göre kaydediliyor ve orana göre sıralamak ve zaman sırasını korumak istiyorum, ancak bunu kaydetmedim Listedeki zaman damgası. Kısaca söylemek gerekirse, listeyi orana göre sıralamak ve yorumu aynı sırada tutmak istiyorum.
wsysuper

4

Bu arada değiştirilen dokümantasyon ( ilgili taahhüt ) ve mevcut dokümantasyon sortedbunu açıkça garanti etmektedir:

Yerleşik sorted()işlevin kararlı olması garanti edilir. Bir sıralama, eşit olarak karşılaştırılan öğelerin göreli sırasını değiştirmemeyi garanti ediyorsa kararlıdır - bu, birden çok geçişte sıralama yapmak için yararlıdır (örneğin, bölüme göre, ardından maaş derecesine göre sıralama).

Dokümantasyonun bu kısmı Python 2.7 ve Python 3.4 (+) 'a eklendi, bu nedenle bu dil sürümünün uyumlu herhangi bir uygulamasının kararlı olması gerekirsorted .

CPython için Python 2.3'tenlist.sort beri kararlı olduğunu unutmayın.

  • Tim Peters, list.sort()uygulamasını yeniden yazdı - bu bir "kararlı sıralama" (eşit girdiler çıktıda aynı sırada görünür) ve öncekinden daha hızlı.

% 100 emin değilim sorted, günümüzde basit kullanımları list.sort, ancak bunun için geçmişe bakmadım. Ama muhtemelen "her zaman" kullanılmış list.sort.


0

Python 2.4 için "Yenilikler" docs etkin bir "resmi" docs olsa gerekmez sıralanmış noktası () ilk önce, bir liste oluşturur garanti sunmak, üzerinde sıralama () çağrıları yapmak. Gerçekten endişeliyseniz, kaynağı da kontrol edebilirsiniz.


1
Nerede olduğunu gösterir misin? Sıralanmış () "yerinde list.sort () gibi çalışır" ve "yeni oluşturulmuş bir kopya sıralanır" diyor, ancak dahili olarak sort () kullandığını söylemiyorum.
sundar - Monica'yı yeniden etkinleştir

Oluşturulan "kopya" bir listedir (dönüş değeri olarak elde ettiğiniz şey budur) ve dönmeden önce bu listede .sort () çağrılır. QED. Hayır, bu tartışılmaz bir kanıt değil, ancak Python resmi bir standarda sahip olana kadar bunu anlamayacaksınız.
Peter Hansen

0

Sıralamayla ilgili Python 3.6 dokümanı artık şunu belirtmektedir:

Sıraların istikrarlı olması garanti edilir

Ayrıca, bu belgede, kararlı Timsort'a bir bağlantı vardır.

Timsort, 2.3 sürümünden beri Python'un standart sıralama algoritması olmuştur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.