Python ma stabilne sortowanie, więc jeśli wydajność nie jest problemem, najprostszym sposobem jest posortowanie go według pola 2, a następnie sortowanie ponownie według pola 1.
To da ci pożądany wynik, jedyny haczyk polega na tym, że jeśli jest to duża lista (lub chcesz ją często sortować) dwukrotne wywołanie sort może być niedopuszczalnym narzutem.
list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))
Zrobienie tego w ten sposób ułatwia również obsługę sytuacji, w której chcesz, aby niektóre kolumny były sortowane odwrotnie, po prostu dołącz parametr „reverse = True”, gdy jest to konieczne.
W przeciwnym razie możesz przekazać wiele parametrów do itemgetter lub ręcznie utworzyć krotkę. Prawdopodobnie będzie to szybsze, ale problem polega na tym, że nie uogólnia się dobrze, jeśli niektóre kolumny chcą być sortowane odwrotnie (kolumny numeryczne nadal można odwrócić, negując je, ale to zatrzymuje sortowanie).
Więc jeśli nie potrzebujesz żadnych kolumn posortowanych odwrotnie, przejdź do wielu argumentów do itemgetter, jeśli możesz, a kolumny nie są numeryczne lub chcesz, aby sortowanie było stabilne dla wielu kolejnych sortowań.
Edycja: dla komentujących, którzy mają problemy ze zrozumieniem, w jaki sposób odpowiada to pierwotnemu pytaniu, oto przykład, który dokładnie pokazuje, w jaki sposób stabilny charakter sortowania zapewnia, że możemy wykonać oddzielne sortowanie dla każdego klucza i skończyć z danymi posortowanymi według wielu kryteriów:
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))
To jest przykład, który można uruchomić, ale aby uratować ludzi, którzy go uruchamiają, otrzymujemy:
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
Zwróć uwagę w szczególności, jak w drugim kroku reverse=True
parametr utrzymuje pierwsze nazwiska w kolejności, podczas gdy zwykłe sortowanie, a następnie odwracanie listy spowoduje utratę żądanej kolejności dla trzeciego klucza sortowania.