Python ha un ordinamento stabile, quindi a condizione che le prestazioni non costituiscano un problema, il modo più semplice è quello di ordinarlo per campo 2 e quindi di ordinarlo nuovamente per campo 1.
Questo ti darà il risultato che desideri, l'unico problema è che se si tratta di un grande elenco (o se vuoi ordinarlo spesso) chiamare l'ordinamento due volte potrebbe essere un sovraccarico inaccettabile.
list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))
Farlo in questo modo semplifica anche la gestione della situazione in cui si desidera ordinare alcune colonne inverse, basta includere il parametro 'reverse = True' quando necessario.
Altrimenti puoi passare più parametri a itemgetter o creare manualmente una tupla. Probabilmente sarà più veloce, ma ha il problema che non si generalizza bene se alcune colonne vogliono essere ordinate al contrario (le colonne numeriche possono ancora essere invertite negandole ma ciò impedisce che l'ordinamento sia stabile).
Quindi se non hai bisogno di colonne ordinate al contrario, vai su più argomenti a itemgetter, se possibile, e le colonne non sono numeriche o vuoi mantenere l'ordinamento stabile per più ordinamenti consecutivi.
Modifica: per i commentatori che hanno problemi a capire come questo risponde alla domanda originale, ecco un esempio che mostra esattamente come la natura stabile dell'ordinamento ci assicura che possiamo fare ordinamenti separati su ogni chiave e finire con i dati ordinati su più criteri:
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))
Questo è un esempio eseguibile, ma per salvare le persone che lo eseguono l'output è:
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
Si noti in particolare come nella seconda fase il reverse=Trueparametro mantiene in ordine i nomi, mentre semplicemente ordinando e invertendo l'elenco si perderebbe l'ordine desiderato per la terza chiave di ordinamento.