问题:如何根据对象的属性对对象列表进行排序?
我有一个Python对象列表,我想按对象本身的属性对其进行排序。该列表如下所示:
>>> ut
[<Tag: 128>, <Tag: 2008>, <Tag: <>, <Tag: actionscript>, <Tag: addresses>,
<Tag: aes>, <Tag: ajax> ...]
每个对象都有一个计数:
>>> ut[1].count
1L
我需要按递减计数对列表进行排序。
我已经看到了几种方法,但是我正在寻找Python的最佳实践。
回答 0
# 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)
有关按键排序的更多信息。
回答 1
可以使用最快的方法,尤其是在您的列表中有很多记录的情况下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
回答 2
读者应注意,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倍左右。他们说的原因是由于python(timsort)中使用了高度优化的排序算法。
仍然,.sort(lambda)比普通的旧.sort()快是很奇怪的。我希望他们能解决这个问题。
回答 3
面向对象的方法
最好将对象排序逻辑(如果适用)设置为类的属性,而不是在每个实例中都要求进行排序。
这样可以确保一致性,并且不需要样板代码。
至少,您应该指定__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]
回答 4
from operator import attrgetter
ut.sort(key = attrgetter('count'), reverse = True)
回答 5
它看起来很像Django ORM模型实例的列表。
为什么不对这样的查询进行排序:
ut = Tag.objects.order_by('-count')
回答 6
回答 7
如果要排序的属性是property,则可以避免导入,operator.attrgetter
而可以使用属性的fget
方法。
例如,对于Circle
具有属性的类,radius
我们可以circles
按如下所示对半径列表进行排序:
result = sorted(circles, key=Circle.radius.fget)
这不是最知名的功能,但通常使我免于导入的麻烦。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。