Frage

Ich habe eine Liste von Python-Objekte, die ich selbst durch ein Attribut der Objekte sortieren möchten. Die Liste wie folgt aussieht:

>>> ut
[<Tag: 128>, <Tag: 2008>, <Tag: <>, <Tag: actionscript>, <Tag: addresses>,
 <Tag: aes>, <Tag: ajax> ...]

Jedes Objekt hat eine Zählung:

>>> ut[1].count
1L

Ich brauche absteigend die Liste nach Anzahl der Zählungen zu sortieren.

Ich habe für diese verschiedenen Methoden gesehen, aber ich bin für die beste Praxis in Python suchen.

War es hilfreich?

Lösung

# 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 Sortierung von Tasten »

Andere Tipps

Eine Art und Weise, die am schnellsten sein kann, vor allem, wenn Ihre Liste viele Datensätze hat, ist operator.attrgetter("count") zu verwenden. Allerdings könnte dies auf einer Pre-Operator Version von Python laufen, also es wäre schön, einen Fallback-Mechanismus zu haben. Vielleicht möchten Sie folgendes tun, dann:

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

Die Leser sollten beachten, dass der Schlüssel = Methode:

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

ist ein Vielfaches schneller als das Hinzufügen reichen Vergleichsoperatoren zu den Objekten. Ich war überrascht, diese (Seite 485 von „Python in a Nutshell“) zu lesen. Sie können dies bestätigen durch Tests auf diesem kleinen Programm ausgeführt wird:

#!/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

My, sehr minimal, zeigen Tests die erste Art mehr als 10-mal langsamer, aber das Buch sagt, dass es nur etwa 5-mal langsamer im Allgemeinen. Der Grund, warum sie sagen, ist aufgrund der Optimierung sehr Sortieralgorithmus in Python verwendet ( Timsort ).

Still, es ist sehr seltsam, dass .Sort (Lambda) ist schneller als normale alte .Sort (). Ich hoffe, dass sie das in Ordnung bringen.

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

Die objektorientierte Ansatz

Es ist eine gute Übung, um Objektsortierlogik zu machen ggf. eine Eigenschaft der Klasse und nicht der Bestellung erforderlich ist, in jedem Fall aufgenommen wird.

Dies gewährleistet die Konsistenz und beseitigt die Notwendigkeit für Standardcode.

Als Minimum sollten Sie __eq__ und __lt__ Operationen angeben, für diese zu arbeiten. Dann einfach sorted(list_of_objects) verwenden.

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]

Es sieht aus wie eine Liste von Django ORM Modellinstanzen.

Warum sie nicht auf Abfrage sortiert werden wie folgt aus:

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