Ich habe eine Liste von Python-Objekten, die ich nach einem Attribut der Objekte selbst sortieren möchte. Die Liste sieht aus wie:
>>> ut
[<Tag: 128>, <Tag: 2008>, <Tag: <>, <Tag: actionscript>, <Tag: addresses>,
<Tag: aes>, <Tag: ajax> ...]
Jedes Objekt hat eine Anzahl:
>>> ut[1].count
1L
Ich muss die Liste nach absteigender Anzahl sortieren.
Ich habe verschiedene Methoden dafür gesehen, aber ich suche nach Best Practices in Python.
Antworten:
Mehr zum Sortieren nach Schlüsseln .
quelle
Ein Weg, der am schnellsten sein kann, insbesondere wenn Ihre Liste viele Datensätze enthält, ist die Verwendung
operator.attrgetter("count")
. Dies könnte jedoch auf einer Voroperatorversion von Python ausgeführt werden, daher wäre es schön, einen Fallback-Mechanismus zu haben. Dann möchten Sie vielleicht Folgendes tun:quelle
self.__dict__ = {'some':'dict'}
nach der__init__
Methode getan haben ). Ich weiß allerdings nicht, warum es anders sein sollte.__dict__
. Beachten Sie, dass "ein Objekt mit dynamisch hinzugefügten Attributen" und "Festlegen des__dict__
Attributs eines Objekts " fast orthogonale Konzepte sind. Ich sage das, weil Ihr Kommentar zu implizieren scheint, dass das Festlegen des__dict__
Attributs eine Voraussetzung für das dynamische Hinzufügen von Attributen ist.operator.attrgetter
, könnte ich eine Funktion mit einem beliebigen Eigenschaftsnamen angeben und eine sortierte Sammlung zurückgeben.Leser sollten beachten, dass der Schlüssel = Methode:
ist um ein Vielfaches schneller als das Hinzufügen umfangreicher Vergleichsoperatoren zu den Objekten. Ich war überrascht, dies zu lesen (Seite 485 von "Python in a Nutshell"). Sie können dies bestätigen, indem Sie Tests mit diesem kleinen Programm ausführen:
Meine sehr minimalen Tests zeigen, dass die erste Sorte mehr als zehnmal langsamer ist, aber das Buch sagt, dass sie im Allgemeinen nur fünfmal langsamer ist. Der Grund dafür liegt in dem hochoptimierten Sortieralgorithmus, der in Python ( Timsort ) verwendet wird.
Trotzdem ist es sehr seltsam, dass .sort (Lambda) schneller ist als einfaches altes .sort (). Ich hoffe, dass sie das beheben.
quelle
__cmp__
ist gleichbedeutend mit dem Aufrufen.sort(cmp=lambda)
, nicht.sort(key=lambda)
, also ist es überhaupt nicht seltsam.longList2.sort(cmp = cmp)
. Ich habe das ausprobiert und es lief fast genauso wie.sort()
. (Beachten Sie auch, dass der Sortierparameter "cmp" in Python 3 entfernt wurde.)Objektorientierter Ansatz
Es wird empfohlen, die Objektsortierlogik gegebenenfalls zu einer Eigenschaft der Klasse zu machen, anstatt sie in jede Instanz einzubeziehen, für die die Reihenfolge erforderlich ist.
Dies stellt die Konsistenz sicher und macht Boilerplate-Code überflüssig.
Zumindest sollten Sie angeben
__eq__
und__lt__
Operationen ausführen, damit dies funktioniert. Dann einfach benutzensorted(list_of_objects)
.quelle
__eq__
und__lt__
welche Mindestanforderungen für die Implementierung gelten?•The sort routines are guaranteed to use __lt__() when making comparisons between two objects...
quelle
Es ähnelt einer Liste von Django ORM-Modellinstanzen.
Warum sortieren Sie sie nicht bei Abfragen wie folgt:
quelle
Fügen Sie der Objektklasse umfangreiche Vergleichsoperatoren hinzu, und verwenden Sie dann die sort () -Methode der Liste.
Siehe reichhaltigen Vergleich in Python .
Update : Obwohl diese Methode funktionieren würde, denke ich, dass die Lösung von Triptychon besser für Ihren Fall geeignet ist, weil sie viel einfacher ist.
quelle
Wenn das Attribut, nach dem Sie sortieren möchten, eine Eigenschaft ist , können Sie das Importieren
operator.attrgetter
und Verwenden der Eigenschaft vermeidenfget
stattdessen Methode verwenden.Für eine Klasse
Circle
mit einer Eigenschaftradius
könnten wir beispielsweise eine Listecircles
nach Radien wie folgt sortieren :Dies ist nicht die bekannteste Funktion, erspart mir aber oft eine Zeile beim Import.
quelle