Python a un tri stable, donc à condition que les performances ne soient pas un problème, le moyen le plus simple est de le trier par champ 2, puis de le trier à nouveau par champ 1.
Cela vous donnera le résultat que vous voulez, le seul hic, c'est que s'il s'agit d'une grande liste (ou si vous voulez la trier souvent), appeler tri deux fois peut être une surcharge inacceptable.
list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))
En procédant de cette manière, il est également facile de gérer la situation dans laquelle vous souhaitez que certaines des colonnes soient triées de manière inversée, incluez simplement le paramètre 'reverse = True' si nécessaire.
Sinon, vous pouvez transmettre plusieurs paramètres à itemgetter ou créer manuellement un tuple. Cela va probablement être plus rapide, mais a le problème que cela ne se généralise pas bien si certaines des colonnes veulent être triées par inversion (les colonnes numériques peuvent toujours être inversées en les annulant, mais cela empêche le tri d'être stable).
Donc, si vous n'avez pas besoin de colonnes triées inversement, optez pour plusieurs arguments dans itemgetter, si vous le pouvez, et les colonnes ne sont pas numériques ou si vous voulez garder le tri stable pour plusieurs tris consécutifs.
Edit: Pour les commentateurs qui ont du mal à comprendre comment cela répond à la question d'origine, voici un exemple qui montre exactement comment la nature stable du tri garantit que nous pouvons faire des tris séparés sur chaque clé et finir avec des données triées sur plusieurs critères:
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))
Ceci est un exemple exécutable, mais pour sauver les personnes qui l'exécutent, le résultat est:
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
Notez en particulier comment dans la deuxième étape le reverse=True
paramètre maintient les prénoms dans l'ordre alors que le simple tri puis l'inversion de la liste perdraient l'ordre souhaité pour la troisième clé de tri.