J'ai la liste suivante créée à partir d'un CSV trié
list1 = sorted(csv1, key=operator.itemgetter(1))
En fait, j'aimerais trier la liste en fonction de deux critères: d'abord par la valeur du champ 1, puis par la valeur du champ 2. Comment procéder?
comme ça:
import operator
list1 = sorted(csv1, key=operator.itemgetter(1, 2))
Répondre à ce fil mort pour archive.
Pas besoin d'importer quoi que ce soit lors de l'utilisation des fonctions lambda.
Le tri suivant list
par le premier élément, puis par le deuxième élément.
sorted(list, key=lambda x: (x[0], -x[1]))
Python a un tri stable. Par conséquent, à condition que les performances ne soient pas un problème, le moyen le plus simple est de les trier par champ 2, puis de les trier à nouveau par champ 1.
Cela vous donnera le résultat que vous voulez, le seul problème est que s'il s'agit d'une liste volumineuse (ou si vous voulez trier celle-ci souvent), le fait de trier deux fois pourrait être un temps système inacceptable.
list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))
Cette façon de procéder facilite également la gestion de la situation dans laquelle certaines colonnes doivent être triées de manière inversée. Vous devez simplement inclure 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 le problème est que cela ne se généralise pas bien si certaines colonnes veulent être triées de manière inverse (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 en sens inverse, attribuez à itemgetter plusieurs arguments, si vous le permettez, et si les colonnes ne sont pas numériques ou si vous souhaitez que le tri soit stable, réglez plusieurs tris consécutifs.
Edit: Pour les commentateurs qui ont du mal à comprendre comment cela répond à la question initiale, voici un exemple qui montre exactement comment la nature stable du tri garantit que nous pouvons effectuer des tris séparés sur chaque touche et aboutir à 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 gens qui l’exécutent, le résultat est le suivant:
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 paramètre reverse=True
garde les premiers noms en ordre alors que simplement le tri puis l’inversion de la liste perdent l’ordre souhaité pour la troisième clé de tri.
def keyfunc(x):
return Tuple(x[1],x[2])
list1 = sorted(csv1, key=keyfunc)
employees.sort(key = lambda x:x[1])
employees.sort(key = lambda x:x[0])
Nous pouvons également utiliser .sort avec lambda 2 fois, car le type python est en place et stable. Cela va d'abord trier la liste en fonction du deuxième élément, x [1]. Ensuite, il va trier le premier élément, x [0] (priorité la plus élevée).
employés [0] = nom de l'employé employés [1] = salaire de l'employé
Cela équivaut à effectuer ce qui suit: employés.sort (clé = lambda x: (x [0], x [1]))
Dans l'ordre croissant, vous pouvez utiliser:
sorted_data= sorted(non_sorted_data, key=lambda k: (k[1],k[0]))
ou par ordre décroissant, vous pouvez utiliser:
sorted_data= sorted(non_sorted_data, key=lambda k: (k[1],k[0]),reverse=True)
En triant la liste des dictés en utilisant ci-dessous, la liste sera triée par ordre décroissant dans la première colonne sous forme de salaire et dans la deuxième colonne par âge
d=[{'salary':123,'age':23},{'salary':123,'age':25}]
d=sorted(d, key=lambda i: (i['salary'], i['age']),reverse=True)
Résultat: [{'salaire': 123, 'âge': 25}, {'salaire': 123, 'âge': 23}]