Wie sortiere ich eine Liste von Objekten basierend auf einem Attribut der Objekte in absteigender Reihenfolge?

Lesezeit: 6 Minuten

Benutzeravatar von Nick Sergeant
Nick Sergeant

Ich habe eine Liste von Python-Objekten, die ich nach einem bestimmten Attribut jedes Objekts sortieren möchte:

>>> ut
[Tag(name="toe", count=10), Tag(name="leg", count=2), ...]

Wie sortiere ich die Liste nach .count in absteigender Reihenfolge?

  • Dupe: stackoverflow.com/questions/157424/…, stackoverflow.com/questions/222752/…, stackoverflow.com/questions/327191/…

    – S. Lott

    31. Dezember 2008 um 18:23 Uhr

  • Sortieren, wie für diejenigen, die nach weiteren Informationen zum Sortieren in Python suchen.

    – Jeyekomon

    30. Mai 2018 um 8:48 Uhr

  • abgesehen von operator.attrgetter(‘attribute_name’) können Sie auch Funktoren als Schlüssel wie object_list.sort(key=my_sorting_functor(‘my_key’) verwenden und die Implementierung bewusst weglassen.

    – Vijay Shanker

    8. April 2019 um 20:07 Uhr

Benutzeravatar von Kenan Banks
Kenan-Banken

# To sort the list in place...
ut.sort(key=lambda x: x.count, reverse=True)

# To return a new list, use the sorted() built-in function...
newlist = sorted(ut, key=lambda x: x.count, reverse=True)

Mehr dazu Sortierung nach Schlüsseln.

  • Kein Problem. Übrigens, wenn muhuk Recht hat und es sich um eine Liste von Django-Objekten handelt, sollten Sie seine Lösung in Betracht ziehen. Für den allgemeinen Fall des Sortierens von Objekten ist meine Lösung jedoch wahrscheinlich die beste Vorgehensweise.

    – Kenan-Banken

    31. Dezember 2008 um 17:12 Uhr

  • Bei großen Listen erhalten Sie eine bessere Leistung, wenn Sie operator.attrgetter(‘count’) als Schlüssel verwenden. Dies ist nur eine optimierte (untere) Form der Lambda-Funktion in dieser Antwort.

    – David Eik

    31. Dezember 2008 um 19:35 Uhr

  • Danke für die tolle Antwort. Falls es sich um eine Liste von Wörterbüchern handelt und „count“ einer ihrer Schlüssel ist, muss sie wie folgt geändert werden: ut.sort(key=lambda x: x[‘count’]umgekehrt = wahr)

    – dganesh2002

    8. Dezember 2016 um 21:20 Uhr


  • Ich nehme an, es verdient das folgende Update: Wenn nach mehreren Feldern sortiert werden muss, kann dies durch aufeinanderfolgende Aufrufe von sort() erreicht werden, da Python einen stabilen Sortieralgorithmus verwendet.

    – uuu777

    23. Februar 2020 um 14:41 Uhr

  • Danke @KenanBanks, du hattest Recht. Ärgerlicherweise machte Outlook einige seltsame Dinge mit Kalenderzeitzonen, so dass einige ohne die Zeitzonendetails durchkamen … keine Ahnung warum!

    – Schmied

    20. April 2022 um 6:05 Uhr

Benutzeravatar von tzot
tzot

Eine Möglichkeit, die 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 Pre-Operator-Version von Python ausgeführt werden, daher wäre es schön, einen Fallback-Mechanismus zu haben. Vielleicht möchten Sie dann Folgendes tun:

try: import operator
except ImportError: keyfun= lambda x: x.count # use a lambda if no operator module
else: keyfun= operator.attrgetter("count") # use operator since it's faster than lambda

ut.sort(key=keyfun, reverse=True) # sort in-place

  • Hier würde ich den Variablennamen „keyfun“ anstelle von „cmpfun“ verwenden, um Verwirrung zu vermeiden. Die Methode sort() akzeptiert auch eine Vergleichsfunktion über das Argument cmp=.

    – akaihola

    2. Januar 2009 um 12:16 Uhr

  • Dies scheint nicht zu funktionieren, wenn das Objekt dynamisch hinzugefügte Attribute hat (falls Sie dies getan haben self.__dict__ = {'some':'dict'} nach dem __init__ Methode). Ich wüsste aber nicht, warum es anders sein sollte.

    – tutuca

    7. Januar 2013 um 20:40 Uhr


  • @tutuca: Ich habe die Instanz nie ersetzt __dict__. Beachten Sie, dass „ein Objekt mit dynamisch hinzugefügten Attributen“ und „ein Objekt festlegen __dict__ Attribut” sind fast orthogonale Konzepte. Ich sage das, weil Ihr Kommentar zu implizieren scheint, dass die Einstellung der __dict__ Das Attribut ist eine Voraussetzung für das dynamische Hinzufügen von Attributen.

    – zot

    9. Januar 2013 um 23:14 Uhr


  • @tzot: Wenn ich die Verwendung von verstehe operator.attrgetterkönnte ich eine Funktion mit einem beliebigen Eigenschaftsnamen bereitstellen und eine sortierte Sammlung zurückgeben.

    – IAbstract

    24. Februar 2016 um 18:16 Uhr

  • Für diejenigen, die weitere Informationen suchen: wiki.python.org/moin/HowTo/Sorting#Operator_Module_Functions

    – alx

    20. Januar 2017 um 15:01 Uhr

Benutzeravatar von Jose M Vidal
José M. Vidal

Leser sollten beachten, dass die Methode key=:

ut.sort(key=lambda x: x.count, reverse=True)

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:

#!/usr/bin/env python
import random

class C:
    def __init__(self,count):
        self.count = count

    def __cmp__(self,other):
        return cmp(self.count,other.count)

longList = [C(random.random()) for i in xrange(1000000)] #about 6.1 secs
longList2 = longList[:]

longList.sort() #about 52 - 6.1 = 46 secs
longList2.sort(key = lambda c: c.count) #about 9 - 6.1 = 3 secs

Meine sehr minimalen Tests zeigen, dass die erste Sorte mehr als 10-mal langsamer ist, aber das Buch sagt, dass sie im Allgemeinen nur etwa 5-mal langsamer ist. Der Grund, den sie sagen, ist auf den hochoptimierten Sortieralgorithmus zurückzuführen, der in Python verwendet wird (Zeitsort).

Trotzdem ist es sehr seltsam, dass .sort(lambda) schneller ist als das einfache alte .sort(). Ich hoffe, sie beheben das.

  • Definieren __cmp__ ist gleichbedeutend mit anrufen .sort(cmp=lambda)nicht .sort(key=lambda)also ist es überhaupt nicht seltsam.

    – zot

    9. September 2019 um 7:46 Uhr

  • @tzot ist genau richtig. Die erste Sorte muss immer wieder Gegenstände miteinander vergleichen. Die zweite Sortierung greift nur einmal auf jedes Objekt zu, um seinen Zählwert zu extrahieren, und führt dann eine einfache numerische Sortierung durch, die hochoptimiert ist. Ein fairer Vergleich wäre longList2.sort(cmp = cmp). Ich habe das ausprobiert und es hat fast die gleiche Leistung erbracht wie .sort(). (Außerdem: Beachten Sie, dass der Sortierparameter „cmp“ in Python 3 entfernt wurde.)

    – Bryan Roach

    29. Oktober 2019 um 4:56 Uhr

  • cmp war in Python 3 veraltet: docs.python.org/3/howto/…

    – Neves

    2. Februar 2021 um 22:40 Uhr

Objektorientierter Ansatz

Es empfiehlt sich, die Objektsortierlogik, falls zutreffend, zu einer Eigenschaft der Klasse zu machen, anstatt sie in jeder Instanz zu integrieren, in der die Reihenfolge erforderlich ist.

Dies gewährleistet Konsistenz und macht Boilerplate-Code überflüssig.

Sie sollten mindestens angeben __eq__ Und __lt__ Operationen, damit dies funktioniert. Dann einfach verwenden sorted(list_of_objects).

class Card(object):

    def __init__(self, rank, suit):
        self.rank = rank
        self.suit = suit

    def __eq__(self, other):
        return self.rank == other.rank and self.suit == other.suit

    def __lt__(self, other):
        return self.rank < other.rank

hand = [Card(10, 'H'), Card(2, 'h'), Card(12, 'h'), Card(13, 'h'), Card(14, 'h')]
hand_order = [c.rank for c in hand]  # [10, 2, 12, 13, 14]

hand_sorted = sorted(hand)
hand_sorted_order = [c.rank for c in hand_sorted]  # [2, 10, 12, 13, 14]

from operator import attrgetter
ut.sort(key = attrgetter('count'), reverse = True)

Benutzeravatar von muhuk
Muhuk

Es sieht aus wie eine Liste von Django-ORM-Modellinstanzen.

Warum sortieren Sie sie nicht nach Abfrage wie folgt:

ut = Tag.objects.order_by('-count')

Benutzeravatar von rob
rauben

Fügen Sie der Objektklasse umfangreiche Vergleichsoperatoren hinzu und verwenden Sie dann die Methode sort() der Liste.
Sehen reichhaltiger Vergleich in Python.


Aktualisieren: Obwohl diese Methode funktionieren würde, denke ich, dass die Lösung von Triptych für Ihren Fall besser geeignet ist, weil sie viel einfacher ist.

1443500cookie-checkWie sortiere ich eine Liste von Objekten basierend auf einem Attribut der Objekte in absteigender Reihenfolge?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy