Python có một loại sắp xếp ổn định, do đó với điều kiện hiệu năng không phải là vấn đề, cách đơn giản nhất là sắp xếp nó theo trường 2 và sau đó sắp xếp lại theo trường 1.
Điều đó sẽ mang lại cho bạn kết quả mà bạn muốn, điều hấp dẫn duy nhất là nếu đó là một danh sách lớn (hoặc bạn muốn sắp xếp nó thường xuyên) thì việc gọi sắp xếp hai lần có thể là một chi phí không thể chấp nhận được.
list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))
Làm theo cách này cũng giúp bạn dễ dàng xử lý tình huống mà bạn muốn một số cột được sắp xếp ngược lại, chỉ cần bao gồm tham số 'Reverse = True' khi cần thiết.
Nếu không, bạn có thể truyền nhiều tham số cho itemgetter hoặc tự tạo một tuple. Điều đó có thể sẽ nhanh hơn, nhưng có một vấn đề là nó không khái quát tốt nếu một số cột muốn được sắp xếp ngược lại (các cột số vẫn có thể được đảo ngược bằng cách phủ định chúng nhưng điều đó ngăn việc sắp xếp ổn định).
Vì vậy, nếu bạn không cần bất kỳ cột nào được sắp xếp ngược lại, hãy chuyển nhiều đối số sang itemgetter, nếu bạn có thể và các cột không phải là số hoặc bạn muốn giữ ổn định sắp xếp cho nhiều loại liên tiếp.
Chỉnh sửa: Đối với những người bình luận có vấn đề hiểu cách trả lời câu hỏi ban đầu, đây là một ví dụ cho thấy chính xác tính chất ổn định của việc sắp xếp đảm bảo chúng ta có thể phân loại riêng biệt trên mỗi khóa và kết thúc với dữ liệu được sắp xếp theo nhiều tiêu chí:
DATA = [
('Jones', 'Jane', 58),
('Smith', 'Anne', 30),
('Jones', 'Fred', 30),
('Smith', 'John', 60),
('Smith', 'Fred', 30),
('Jones', 'Anne', 30),
('Smith', 'Jane', 58),
('Smith', 'Twin2', 3),
('Jones', 'John', 60),
('Smith', 'Twin1', 3),
('Jones', 'Twin1', 3),
('Jones', 'Twin2', 3)
]
# Sort by Surname, Age DESCENDING, Firstname
print("Initial data in random order")
for d in DATA:
print("{:10s} {:10s} {}".format(*d))
print('''
First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred''')
DATA.sort(key=lambda row: row[1])
for d in DATA:
print("{:10s} {:10s} {}".format(*d))
print('''
Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.''')
DATA.sort(key=lambda row: row[2], reverse=True)
for d in DATA:
print("{:10s} {:10s} {}".format(*d))
print('''
Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.
''')
DATA.sort(key=lambda row: row[0])
for d in DATA:
print("{:10s} {:10s} {}".format(*d))
Đây là một ví dụ có thể chạy được, nhưng để cứu người đang chạy nó, đầu ra là:
Initial data in random order
Jones Jane 58
Smith Anne 30
Jones Fred 30
Smith John 60
Smith Fred 30
Jones Anne 30
Smith Jane 58
Smith Twin2 3
Jones John 60
Smith Twin1 3
Jones Twin1 3
Jones Twin2 3
First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred
Smith Anne 30
Jones Anne 30
Jones Fred 30
Smith Fred 30
Jones Jane 58
Smith Jane 58
Smith John 60
Jones John 60
Smith Twin1 3
Jones Twin1 3
Smith Twin2 3
Jones Twin2 3
Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.
Smith John 60
Jones John 60
Jones Jane 58
Smith Jane 58
Smith Anne 30
Jones Anne 30
Jones Fred 30
Smith Fred 30
Smith Twin1 3
Jones Twin1 3
Smith Twin2 3
Jones Twin2 3
Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.
Jones John 60
Jones Jane 58
Jones Anne 30
Jones Fred 30
Jones Twin1 3
Jones Twin2 3
Smith John 60
Smith Jane 58
Smith Anne 30
Smith Fred 30
Smith Twin1 3
Smith Twin2 3
Đặc biệt lưu ý cách thức trong bước thứ hai, reverse=True
tham số giữ các tên đầu tiên theo thứ tự trong khi chỉ cần sắp xếp sau đó đảo ngược danh sách sẽ mất thứ tự mong muốn cho khóa sắp xếp thứ ba.