Hàm sorted () của python có được đảm bảo ổn định không?


96

Các tài liệu không đảm bảo rằng. Có nơi nào khác mà nó được ghi lại không?

Tôi đoán nó có thể ổn định vì phương thức sắp xếp trên danh sách được đảm bảo là ổn định (Lưu ý điểm thứ 9: "Bắt đầu với Python 2.3, phương thức sort () được đảm bảo là ổn định") và sắp xếp tương tự về mặt chức năng. Tuy nhiên, tôi không thể tìm thấy bất kỳ nguồn chính xác nào nói như vậy.

Mục đích: Tôi cần sắp xếp dựa trên khóa chính và cả khóa phụ trong trường hợp khóa chính bằng nhau trong cả hai bản ghi. Nếu đảm bảo rằng sorted () ổn định, tôi có thể sắp xếp trên khóa phụ, sau đó sắp xếp trên khóa chính và nhận được kết quả tôi cần.

Tái bút: Để tránh bất kỳ sự nhầm lẫn nào, tôi đang sử dụng stable theo nghĩa "một sắp xếp ổn định nếu nó đảm bảo không thay đổi thứ tự tương đối của các phần tử so sánh bằng nhau".

Câu trả lời:


127

Đúng vậy, mục đích của hướng dẫn này thực sự là để đảm bảo rằng sortednó ổn định và thực sự rằng nó sử dụng chính xác cùng một thuật toán với sortphương pháp. Tôi nhận ra rằng các tài liệu không rõ ràng 100% về danh tính này; bản vá doc luôn được chấp nhận một cách vui vẻ!


2
Tôi nhận thấy rằng nếu tôi đang sắp xếp các bộ giá trị hoặc danh sách, bất cứ khi nào các khóa sắp xếp "chính" bằng nhau, thì nó sẽ sắp xếp theo khóa "phụ". Ví dụ: sorted([(1, 2), (1, 1)])trả về [(1, 1), (1, 2)]thay vì trả về đầu vào ban đầu trong cùng một trình tự / thứ tự. Không phải đảm bảo sự ổn định có nghĩa là nó phải trả lại đầu [(1, 2), (1, 1)]vào ban đầu? Trong trường hợp đó, bạn phải rõ ràng và nóisorted([(1, 2), (1, 1)], key=lambda t: t[0])
code_dredd

10
Đây không phải là những gì được mong đợi trong trường hợp này? Theo mặc định, Python sẽ so sánh các bộ giá trị thông qua tất cả các phần tử, không chỉ phần tử "chính" đầu tiên. Nếu bạn chỉ muốn sắp xếp trên phần tử đầu tiên, bạn có thể truyền keytham số một cách rõ ràng.
Matias Grioni

2
@code_dredd đây là hành vi được mong đợi. Điểm của sắp xếp ổn định là sắp xếp bằng cách sử dụng "khóa sắp xếp" nhưng hai phần tử khác nhau có cùng khóa sắp xếp sẽ theo cùng một thứ tự. Khóa sắp xếp mặc định cho một bộ là tất cả các phần tử của bộ.
guyarad

27

Chúng ổn định .

Nhân tiện: đôi khi bạn có thể bỏ qua việc biết liệu sắp xếp và sắp xếp có ổn định hay không, bằng cách kết hợp một loại nhiều lần chuyển trong một lần chuyển.

Ví dụ, nếu bạn muốn loại đối tượng dựa trên của họ last_name, first_namethuộc tính, bạn có thể làm điều đó trong một đường chuyền:

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

tận dụng lợi thế của so sánh tuple.

Câu trả lời này, nguyên trạng, bao hàm câu hỏi ban đầu. Đối với các câu hỏi liên quan đến sắp xếp thêm, có Cách sắp xếp trong Python .


4
Điều này có thể có tác dụng không mong muốn nếu bạn muốn đảo ngược việc sắp xếp. Ví dụ: khi phân loại sản phẩm, trước tiên bạn có thể muốn sắp xếp theo xếp hạng (thứ tự tăng dần) và sau đó là giá (cũng tăng dần). Nếu bạn đảo ngược điều này, bạn muốn sắp xếp xếp hạng theo thứ tự giảm dần nhưng giá theo thứ tự tăng dần. Điều này không hoạt động với giải pháp này.
Remco Wendt

2
@RemcoWendt: không có yêu cầu đối với những gì bạn mô tả. Trong mọi trường hợp, hãy xem xét key= lambda item: (-item.rating, item.price)hoặc cung cấp một cmpthay vì một keyđối số. Tuy nhiên, tôi vẫn không chắc chắn về mục đích nhận xét của bạn.
tzot

1
Thật vậy, đó không phải là một yêu cầu, nhưng muốn chỉ ra sự khác biệt tinh tế này khi người khác đọc điều này và đưa ra lựa chọn giữa giải pháp của bạn hoặc sử dụng tính năng sắp xếp ổn định của Python.
Remco Wendt

Tôi hiểu rồi. Nói cách khác, sắp xếp theo cặp rõ ràng hơn và do đó được ưu tiên hơn, trừ khi bạn quan tâm đến hiệu suất. Tôi tưởng tượng rằng hai loại ổn định có phần nhanh hơn một loại theo cặp, mặc dù sự khác biệt có thể không đáng kể -?
Sergey Orshanskiy

8
@tzot Tôi muốn đề cập, luôn có những yêu cầu như vậy để sắp xếp ổn định. Ví dụ: tôi có một danh sách các tuple (tỷ lệ, nhận xét), các nhận xét được lưu theo thứ tự khi chúng được đưa ra và tôi muốn sắp xếp theo tỷ lệ và giữ thứ tự thời gian, tuy nhiên, tôi đã không lưu dấu thời gian trong danh sách. Nói một cách ngắn gọn, tôi chỉ muốn sắp xếp danh sách theo tỷ lệ và giữ cho nhận xét theo thứ tự.
wsysuper

3

Tài liệu đã thay đổi trong thời gian chờ đợi ( cam kết có liên quan ) và tài liệu hiện tại sortedđảm bảo rõ ràng rằng:

Việc xây dựng trong sorted()chức năng là đảm bảo được ổn định. Sắp xếp ổn định nếu nó đảm bảo không thay đổi thứ tự tương đối của các phần tử so sánh ngang bằng - điều này hữu ích cho việc sắp xếp theo nhiều lượt (ví dụ: sắp xếp theo bộ phận, sau đó theo cấp bậc lương).

Phần này của tài liệu đã được thêm vào Python 2.7 và Python 3.4 (+), vì vậy bất kỳ triển khai tuân thủ nào của phiên bản ngôn ngữ đó đều phải ổn định sorted.

Lưu ý rằng đối với CPython, nó list.sortđã ổn định kể từ Python 2.3

  • Tim Peters đã viết lại cách list.sort()triển khai của mình - đây là một "sắp xếp ổn định" (các đầu vào bằng nhau xuất hiện theo cùng một thứ tự trong đầu ra) và nhanh hơn trước.

Tôi không chắc chắn 100% sorted, ngày nay nó sử dụng đơn giản list.sort, nhưng tôi chưa kiểm tra lịch sử cho điều đó. Nhưng có khả năng là nó "luôn luôn" được sử dụng list.sort.


0

Tài liệu "Có gì mới" dành cho Python 2.4 thực hiện hiệu quả điểm được sắp xếp () trước tiên tạo ra một danh sách, sau đó gọi sort () trên đó, cung cấp cho bạn sự đảm bảo mà bạn cần mặc dù không có trong tài liệu "chính thức". Bạn cũng có thể chỉ cần kiểm tra nguồn nếu bạn thực sự lo lắng.


1
Bạn có thể chỉ vào nơi nó nói như vậy? Nó nói rằng sorted () "hoạt động giống như list.sort () tại chỗ" và "một bản sao mới hình thành được sắp xếp", nhưng tôi không thấy nó nói rằng nó sử dụng sort () nội bộ.
sundar - Phục hồi Monica

"Bản sao" được hình thành là một danh sách (đó là những gì bạn nhận được dưới dạng giá trị trả về) và .sort () được gọi trong danh sách đó trước khi trả về. QED. Không, nó không phải là một bằng chứng không có sẵn, nhưng cho đến khi Python có một tiêu chuẩn chính thức, bạn sẽ không hiểu được điều đó.
Peter Hansen

0

Tài liệu Python 3.6 về sắp xếp hiện nói rằng

Các loại được đảm bảo ổn định

Hơn nữa, trong tài liệu đó, có một liên kết đến Timsort ổn định , nói rằng

Timsort đã là thuật toán sắp xếp tiêu chuẩn của Python kể từ phiên bản 2.3

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.