개체의 속성을 기반으로 개체 목록을 정렬하는 방법은 무엇입니까?
객체 자체의 속성별로 정렬하려는 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 ()보다 빠르다는 것은 매우 이상합니다. 나는 그들이 그것을 고치기를 바랍니다.
from operator import attrgetter
ut.sort(key = attrgetter('count'), reverse = True)
객체 지향 접근 방식
해당되는 경우 순서가 필요한 각 인스턴스에 통합되는 것보다 객체 정렬 논리를 클래스의 속성으로 만드는 것이 좋습니다.
이렇게하면 일관성이 보장되고 상용구 코드가 필요하지 않습니다.
At a minimum, you should specify __eq__
and __lt__
operations for this to work. Then just use 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]
It looks much like a list of Django ORM model instances.
Why not sort them on query like this:
ut = Tag.objects.order_by('-count')
Add rich comparison operators to the object class, then use sort() method of the list.
See rich comparison in python.
Update: Although this method would work, I think solution from Triptych is better suited to your case because way simpler.
If the attribute you want to sort by is a property, then you can avoid importing operator.attrgetter
and use the property's fget
method instead.
For example, for a class Circle
with a property radius
we could sort a list of circles
by radii as follows:
result = sorted(circles, key=Circle.radius.fget)
This is not the most well-known feature but often saves me a line with the import.
'development' 카테고리의 다른 글
Eclipse IDE에 "프로젝트에서 찾기…"기능이 있습니까? (0) | 2020.09.30 |
---|---|
C #에서 public, private, protected 및 no access modifier의 차이점은 무엇입니까? (0) | 2020.09.30 |
JavaScript 배열에서 임의의 값 가져 오기 (0) | 2020.09.30 |
Java로 새 목록을 만드는 방법 (0) | 2020.09.30 |
jQuery를 사용하여 이미지 소스 변경 (0) | 2020.09.30 |