У Python є стабільний сорт, тому за умови, що продуктивність не є проблемою, найпростішим способом є сортування її за полем 2 та повторне сортування за полем 1.
Це дасть вам результат, який ви хочете, єдиний улов полягає в тому, що якщо це великий список (або ви хочете його сортувати часто), виклик сортування двічі може бути неприйнятним накладним.
list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))
Це також дозволяє легко впоратися з ситуацією, коли ви хочете, щоб деякі стовпці були відсортовані, просто включіть параметр 'reverse = True', коли це необхідно.
В іншому випадку ви можете передати кілька параметрів у itemgetter або вручну побудувати кортеж. Це, мабуть, буде швидше, але є проблема в тому, що він недостатньо добре узагальнюється, якщо деякі стовпці хочуть бути відсортованими в зворотному порядку (числові стовпці все одно можна змінити, відкинувши їх, але це зупиняє сортування стабільним).
Тож якщо вам не потрібні жодні стовпці, відтворені в зворотному порядку, перейдіть до кількох аргументів до itemgetter, якщо це можливо, а стовпці не є числовими або ви хочете тримати сортування стабільним.
Редагувати: Для коментаторів, які мають проблеми з розумінням того, як це відповідає на початкове запитання, ось приклад, який точно показує, як стабільний характер сортування забезпечує те, що ми можемо робити окремі сортування на кожній клавіші і в кінцевому підсумку з даними, відсортованими за кількома критеріями:
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))
Це приклад для запуску, але для того, щоб врятувати людей, які його виконують, вихід:
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
Зокрема, зверніть увагу, як на другому кроці reverse=Trueпараметр підтримує імена в порядку, тоді як просто сортування та повернення списку втратить потрібний порядок для третього ключа сортування.