Trier une liste par plusieurs attributs?
J'ai une liste de listes:
[[12, 'tall', 'blue', 1],
[2, 'short', 'red', 9],
[4, 'tall', 'blue', 13]]
Si je voulais trier par un élément, dire le grand et court élément, je pourrais le faire via s = sorted(s, key = itemgetter(1))
.
Si je voulais trier par les deux grand et court et de couleur, je pourrais faire le tri à deux reprises, une fois pour chaque élément, mais est-il un moyen plus rapide?
- Liées PPCG question
- Si vous utilisez tuples au lieu de listes, python commandes sortes par des entrées de gauche à droite lorsque vous exécutez
sort
. C'est,sorted([(4, 2), (0, 3), (0, 1)]) == [(0, 1), (0, 3), (4, 2)]
.
Vous devez vous connecter pour publier un commentaire.
Une clé peut être une fonction qui renvoie un tuple:
Ou vous pouvez obtenir le même à l'aide de
itemgetter
(qui est plus rapide et évite de Python appel de fonction):Et remarquez que vous pouvez utiliser ici
sort
au lieu d'utilisersorted
et puis réaffectation:timeit
module de mesure de la performance des deux si vous êtes intéressé.-
pour les entiers)revrse=True
seulement àx[1]
est-ce possible ?s = sorted(s, key = operator.itemgetter(2))
puis par le principals = sorted(s, key = operator.itemgetter(1), reverse=True)
Pas l'idéal, mais fonctionne.sorted
est garanti pour être stable (source)-1
.linesOrderedLeft = lines_Left.sort(key= lambda t: (t[0][1],t[0][3]) )
mais il ne fonctionne pas avec moi car je suis en train de trier les tableaux basés sur leur premier et le troisième indice, en faisant la somme jusqu'Alors quel est le problème avec mon codekey = operator.itemgetter(...)
est beaucoup plus rapide quekey = lambda: ...
, et le déplacer vers le haut. Aussi, lambda est inutile plutôt que de itemgetter si le tri personnalisé est seulement accès à plusieurs domaines, et de ne pas les transformer (par exemple, la négation, en minuscules, commande personnalisée, ASCIIbetical ordre, une chaîne d'appels de méthode objet, etc.)reverse=True
est d'envelopper les deux critères de tri dans la parenthèse:s = sorted(s, key=lambda i: ( criteria1(i), criteria2(i) ), reverse=True)
Je ne suis pas sûr si c'est le plus pythonic méthode ...
J'avais une liste de tuples qui devait 1er tri par ordre décroissant des valeurs entières et 2ème ordre alphabétique. Cette nécessaire d'inverser l'entier de tri, mais pas l'ordre alphabétique. C'était ma solution: (à la volée dans un examen btw, je n'étais même pas conscient que vous avez pu " nid " triés fonctions)
b = sorted(a, key = lambda x: (-x[1], x[0]))
qui est plus visible sur les critères qui s'applique en premier. comme pour l'efficacité je ne suis pas sûr, quelqu'un doit timeit.Il semble que vous pourriez utiliser un
list
au lieu d'untuple
.Cela devient de plus en plus important, je pense que lorsque vous prenez les attributs au lieu de " la magie des indices d'une liste ou un tuple.
Dans mon cas, j'ai voulu trier par plusieurs attributs d'une classe, où les entrants les clés sont des chaînes de caractères. J'avais besoin de tri différents dans différents endroits, et je voulais une commune tri par défaut pour la classe parente que les clients ont été en interaction avec; de n'avoir à remplacer les "clés de tri" quand je suis vraiment "nécessaire pour", mais aussi dans une manière que je pourrais stocker sous forme de listes que la classe pourrait partager
Alors d'abord j'ai défini une méthode d'assistance
puis de l'utiliser
Cela utiliser le générés fonction lambda trier la liste par
object.attrA
et puisobject.attrB
en supposantobject
a un getter correspondant à la chaîne les noms fournis. Et le deuxième cas serait de trier parobject.attrC
puisobject.attrA
.Cela permet également à risque d'exposer l'extérieur de tri des choix fragment de la même manière par un consommateur, un test unitaire, ou peut-être vous dire comment ils veulent le tri effectué pour une opération dans votre api en n'avez qu'à vous donner une liste et pas de couplage à votre back-end de mise en œuvre.
Voici un moyen: en gros, Vous ré-écrire votre fonction de tri de prendre une liste de fonctions de tri, chaque fonction de tri compare les attributs que vous souhaitez tester, sur chaque sorte de test, de vous regarder et de voir si la cmp fonction renvoie une valeur non nulle de retour si oui pause et envoyer la valeur de retour.
Vous l'appelez par l'appel d'une Lambda d'une fonction d'une liste de Lambdas.
Son avantage est qu'il ne passe unique à travers les données, et non une sorte de tri précédent que les autres méthodes. Une autre chose est qu'il trie en place, alors que triées semble en faire une copie.
Je l'ai utilisé pour écrire une fonction rang, qui classe une liste de classes où chaque objet est dans un groupe et a une fonction de score, mais vous pouvez ajouter une liste d'attributs.
Note de l'onu-lambda-comme, si hackish utilisation d'un lambda pour appeler un setter.
Le rang de la partie de ne pas travailler pour un tableau de listes, mais le tri doit.
Ici est une façon de classer une liste d'objets
Plusieurs années de retard à la fête, mais je veux les deux tri sur 2 critères et utilisation
reverse=True
. Dans le cas où quelqu'un d'autre veut savoir comment, vous pouvez envelopper vos critères (fonctions) entre parenthèses: