J'ai une liste d'objets Python que j'aimerais trier par attribut des objets eux-mêmes. La liste ressemble à:
>>> ut
[<Tag: 128>, <Tag: 2008>, <Tag: <>, <Tag: actionscript>, <Tag: addresses>,
<Tag: aes>, <Tag: ajax> ...]
Chaque objet a un décompte:
>>> ut[1].count
1L
J'ai besoin de trier la liste par nombre de décomptes décroissants.
J'ai vu plusieurs méthodes pour cela, mais je recherche les meilleures pratiques en Python.
Réponses:
Plus d'informations sur le tri par clés .
la source
Un moyen qui peut être plus rapide, surtout si votre liste contient beaucoup d'enregistrements, est d'utiliser
operator.attrgetter("count")
. Cependant, cela pourrait fonctionner sur une version pré-opérateur de Python, donc ce serait bien d'avoir un mécanisme de secours. Vous pouvez alors faire ce qui suit:la source
self.__dict__ = {'some':'dict'}
après la__init__
méthode). Je ne sais pas pourquoi ça devrait être différent, cependant.__dict__
. Notez que "un objet auquel des attributs ont été ajoutés dynamiquement" et "définir l'__dict__
attribut d' un objet " sont des concepts presque orthogonaux. Je dis cela parce que votre commentaire semble impliquer que la définition de l'__dict__
attribut est une exigence pour l'ajout dynamique d'attributs.operator.attrgetter
, je pourrais fournir une fonction avec n'importe quel nom de propriété et renvoyer une collection triée.Les lecteurs doivent noter que la méthode key =:
est beaucoup plus rapide que l'ajout d'opérateurs de comparaison riches aux objets. J'ai été surpris de lire ceci (page 485 de "Python en bref"). Vous pouvez le confirmer en exécutant des tests sur ce petit programme:
Mes tests, très minimes, montrent que le premier tri est plus de 10 fois plus lent, mais le livre dit qu'il n'est que 5 fois plus lent en général. La raison pour laquelle ils disent est due à l'algorithme de tri hautement optimisé utilisé en python ( timsort ).
Pourtant, il est très étrange que .sort (lambda) soit plus rapide que l'ancien .sort (). J'espère qu'ils corrigent cela.
la source
__cmp__
équivaut à appeler.sort(cmp=lambda)
, non.sort(key=lambda)
, donc ce n'est pas étrange du tout.longList2.sort(cmp = cmp)
. J'ai essayé cela et cela a fonctionné presque comme.sort()
. (Aussi: notez que le paramètre de tri "cmp" a été supprimé dans Python 3.)Approche orientée objet
Il est recommandé de faire de la logique de tri des objets, le cas échéant, une propriété de la classe plutôt qu'incorporée dans chaque instance, le classement est requis.
Cela garantit la cohérence et élimine le besoin de code passe-partout.
Au minimum, vous devez spécifier
__eq__
et les__lt__
opérations pour que cela fonctionne. Ensuite, utilisez simplementsorted(list_of_objects)
.la source
__eq__
et quelles__lt__
sont les exigences minimales de mise en œuvre?•The sort routines are guaranteed to use __lt__() when making comparisons between two objects...
la source
Cela ressemble beaucoup à une liste d'instances de modèle Django ORM.
Pourquoi ne pas les trier sur une requête comme celle-ci:
la source
Ajoutez des opérateurs de comparaison riches à la classe d'objets, puis utilisez la méthode sort () de la liste.
Voir une comparaison riche en python .
Mise à jour : Bien que cette méthode fonctionne, je pense que la solution de Triptych est mieux adaptée à votre cas car beaucoup plus simple.
la source
Si l'attribut que vous souhaitez trier est une propriété , vous pouvez éviter d'importer
operator.attrgetter
et utiliser lafget
méthode de la propriété à la place.Par exemple, pour une classe
Circle
avec une propriété,radius
nous pourrions trier une liste decircles
rayons comme suit:Ce n'est pas la fonctionnalité la plus connue, mais cela me sauve souvent une ligne avec l'importation.
la source