programing

오브젝트 속성을 기반으로 오브젝트 목록을 정렬하려면 어떻게 해야 합니까?

yellowcard 2023. 4. 10. 21:31
반응형

오브젝트 속성을 기반으로 오브젝트 목록을 정렬하려면 어떻게 해야 합니까?

각 객체의 특정 속성을 기준으로 정렬하는 Python 객체의 목록이 있습니다.

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

목록을 정렬하려면 어떻게 해야 합니까?.count내림차순으로?

목록을 정렬하려면:

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

새 목록을 반환하려면sorted:

new_list = sorted(orig_list, key=lambda x: x.count, reverse=True)

설명:

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

는 개체에 리치 비교 연산자를 추가하는 것보다 몇 배 더 빠릅니다.나는 이것을 읽고 놀랐다('호두껍질 속의 피톤' 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() 메서드를 사용합니다.
비단뱀의 풍부한 비교를 볼 수 있습니다.


업데이트: 이 방법은 효과적이지만, Triptich의 솔루션이 훨씬 단순하기 때문에 귀사의 사례에 더 적합하다고 생각합니다.

정렬 기준 속성이 속성인 경우 가져오기를 피할 수 있습니다.operator.attrgetter대신 자산의 메서드를 사용합니다.

예를 들어 클래스의 경우Circle재산을 가지고radius목록을 정렬할 수 있습니다.circles다음과 같이 반지름에 의해:

result = sorted(circles, key=Circle.radius.fget)

이것은 가장 잘 알려진 기능은 아니지만 종종 Import에 대한 설명을 줄여줍니다.

또한 예를 들어 문자열과 숫자가 포함된 목록을 정렬하려는 경우.

 eglist=[
     "some0thing3",
     "some0thing2",
     "some1thing2",
     "some1thing0",
     "some3thing10",
     "some3thing2",
     "some1thing1",
     "some0thing1"]

그 코드는 다음과 같습니다.

import re

def atoi(text):
    return int(text) if text.isdigit() else text

def natural_keys(text):
    return [ atoi(c) for c in re.split(r'(\d+)', text) ]

eglist=[
         "some0thing3",
         "some0thing2",
         "some1thing2",
         "some1thing0",
         "some3thing10",
         "some3thing2",
         "some1thing1",
         "some0thing1"
]

eglist.sort(key=natural_keys)
print(eglist)

언급URL : https://stackoverflow.com/questions/403421/how-do-i-sort-a-list-of-objects-based-on-an-attribute-of-the-objects

반응형