[python] 객체의 속성을 기준으로 객체 목록을 정렬하는 방법은 무엇입니까?

객체 자체의 속성별로 정렬하려는 Python 객체 목록이 있습니다. 목록은 다음과 같습니다.

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

각 객체에는 개수가 있습니다.

>>> ut[1].count
1L

카운트를 내림차순으로 정렬해야합니다.

이에 대한 몇 가지 방법을 보았지만 Python에서 모범 사례를 찾고 있습니다.



답변

# 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)

키를 기준 으로 정렬하는 방법 에 대해 자세히 알아보십시오 .


답변

특히 목록에 많은 레코드가있는 경우 가장 빠른 방법은을 사용하는 것 operator.attrgetter("count")입니다. 그러나 이것은 사전 운영자 버전의 Python에서 실행될 수 있으므로 폴백 메커니즘을 사용하는 것이 좋습니다. 다음을 수행 할 수 있습니다.

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


답변

독자들은 key = 메소드가

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

풍부한 비교 연산자를 객체에 추가하는 것보다 몇 배 더 빠릅니다. 나는 이것을 읽는 것에 놀랐다 ( “Python in a Nutshell”의 485 페이지). 이 작은 프로그램에서 테스트를 실행하여이를 확인할 수 있습니다.

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

저의 테스트는 첫 번째 정렬이 10 배 이상 느리다는 것을 보여 주지만이 책에서는 일반적으로 5 배 정도 느립니다. 그들이 말하는 이유는 파이썬에서 사용되는 정렬 알고리즘을 고도로 최적화했기 때문입니다 ( timsort )에 입니다.

여전히 .sort (lambda)가 일반 .sort ()보다 빠르다는 것은 매우 이상합니다. 나는 그들이 그것을 고치기를 바랍니다.


답변

객체 지향 접근

적용 가능한 경우 개체 정렬 논리를 만드는 것이 좋습니다 (해당되는 경우) 순서가 필요한 각 인스턴스에 포함되지 않고 클래스의 속성.

이를 통해 일관성을 보장하고 상용구 코드가 필요하지 않습니다.

최소한 이 기능이 작동하도록 지정 __eq__하고 __lt__조작 해야 합니다. 그런 다음을 사용하십시오 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)


답변

Django ORM 모델 인스턴스 목록과 매우 비슷합니다.

다음과 같이 쿼리에서 정렬하지 않는 이유는 무엇입니까?

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


답변

풍부한 비교 연산자를 객체 클래스에 추가 한 다음 목록의 sort () 메서드를 사용하십시오. 파이썬에서 풍부한 비교를
참조하십시오 .


업데이트 :이 방법은 효과가 있지만 Triptych의 솔루션이 더 간단하기 때문에 귀하의 경우에 더 적합하다고 생각합니다.