2012-07-13 40 views
27

thể trùng lặp:
How to write Python sort key functions for descending valuesSắp xếp theo nhiều phím sử dụng orderings khác nhau

Trong Python 3, nó khá dễ dàng để sắp xếp một danh sách các đối tượng tự từ điển sử dụng nhiều phím. Ví dụ:

items.sort(key = lambda obj: obj.firstname, obj.lastname)

Đối số reverse cho phép bạn xác định xem bạn muốn tăng dần hoặc giảm dần. Nhưng bạn làm gì trong trường hợp bạn muốn sắp xếp theo nhiều khóa, nhưng bạn muốn sắp xếp bằng cách sử dụng thứ tự giảm dần cho khóa đầu tiên và thứ tự tăng dần cho lần thứ hai?

Ví dụ, giả sử chúng ta có một đối tượng với hai thuộc tính, pointsname, nơi points là một intname là một str. Chúng tôi muốn sắp xếp danh sách các đối tượng này theo số points trong giảm dần đơn đặt hàng (để đối tượng có số điểm lớn nhất đến trước), nhưng đối với các đối tượng có số lượng bằng points, chúng tôi muốn sắp xếp chúng theo name bằng chữ cái (tăng dần) đơn đặt hàng.

Làm cách nào để đạt được điều này?

+2

Ints là trường hợp đặc biệt, trong đó bạn chỉ có thể sử dụng số âm để đặt hàng ngược lại. Tôi muốn được quan tâm nhiều hơn trong trường hợp cả hai đều là dây. –

Trả lời

17

Không có cách tích hợp để xử lý việc này. Đối với trường hợp chung, bạn phải sắp xếp hai lần: trước tiên bằng cách sắp xếp thứ cấp, sau đó là sắp xếp chính. Như @Mark Ransom đã đề cập trong bình luận của mình, trong nhiều trường hợp các biến số là số, và vì vậy bạn có thể sử dụng giá trị âm để lật thứ tự.

Nếu bạn biết loại biến mà bạn đang cố sắp xếp và cách làm việc với biến đó, bạn cũng có thể viết hàm khóa trả về giá trị giảm cho các phím tăng. Xem this thread để biết ví dụ về chuỗi. (Về cơ bản, bạn lấy giá trị bằng số ASCII tiêu cực của các ký tự.)

Trong Python 2, bạn cũng có thể sử dụng hàm cmp thay vì khóa, nhưng điều này có thể làm cho sắp xếp chậm hơn. Cho dù nó sẽ làm cho nó quá chậm phụ thuộc vào cách lớn và unsorted danh sách được. Trong Python 3, đối số cmp đã biến mất, nhưng như ghi chú @Mark Ransom, bạn có thể sử dụng cmp_to_key.

+1

Câu trả lời tuyệt vời, tuy nhiên 'cmp' không còn tồn tại trong python3 (tôi nghĩ). – mgilson

+0

Bạn nói đúng, tôi không nhận thấy câu hỏi này cụ thể về Python 3. Tôi đã chỉnh sửa câu trả lời của mình. – BrenBarn

+0

Tôi đã thấy bản chỉnh sửa của bạn (+1) – mgilson

4

functools.cmp_to_key để chuyển đổi hàm so sánh thành khóa tương thích với các chức năng sắp xếp. Điều này đã được cung cấp cho các loại đã sử dụng một hàm so sánh trong Python 2 và cần được chuyển đổi sang Python 3 vốn không còn cho phép chúng.

Chỉnh sửa: Cũng có một đề xuất trong wiki Python dưới tiêu đề Sort Stability and Complex Sorts để sắp xếp theo nhiều lần, từ khóa ít quan trọng nhất đến quan trọng nhất. Điều này hoạt động vì sắp xếp của Python được đảm bảo ổn định, do đó, thứ tự trước đó được duy trì khi các khóa tương đương gặp phải.

+0

Cảm ơn bạn đã đề xuất sắp xếp ổn định cho phép thực hiện sắp xếp phức tạp trong nhiều lần lặp lại. Thú vị là nó không chậm hơn so với sử dụng 2.x cmp. Tôi tin rằng trong hầu hết các trường hợp phức tạp, cmp sẽ rất tuyệt và có thể loại bỏ nó là một sai lầm. Tôi sợ sử dụng cmp_to_key bởi vì ai biết nó cũng có thể bị bỏ tại một số điểm. –

11
items.sort(key = lambda obj: (obj.firstname, [(-ord(c) for c in obj.lastname)])) 
+0

sẽ không hoạt động vào ngày giờ ... – andi

+0

@andi cách để có thể chuyển đổi ngày unix timestampl int http://stackoverflow.com/questions/1259219/django-datefield-to-unix-timestamp – andi

Các vấn đề liên quan