如何根据对象的属性对对象列表进行排序?
- 2024-11-28 08:37:00
- admin 原创
- 12
问题描述:
我有一个 Python 对象列表,我想按每个对象的特定属性进行排序:
[Tag(name="toe", count=10), Tag(name="leg", count=2), ...]
.count
如何按降序对列表进行排序?
解决方案 1:
对列表进行排序:
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
按降序排序。
有关按键排序的更多信息。
解决方案 2:
一种最快的方法是使用,特别是当你的列表有很多记录时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
解决方案 3:
读者应该注意到key=方法:
ut.sort(key=lambda x: x.count, reverse=True)
比向对象添加丰富的比较运算符要快很多倍。我很惊讶地读到这个(《Python 简明教程》第 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() 更快,这很奇怪。我希望他们能解决这个问题。
解决方案 4:
面向对象方法
如果适用的话,最好将对象排序逻辑作为类的属性,而不是将其纳入每个需要排序的实例中。
这确保了一致性并且消除了对样板代码的需要。
至少,您应该指定__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]
解决方案 5:
from operator import attrgetter
ut.sort(key = attrgetter('count'), reverse = True)
解决方案 6:
它看起来很像 Django ORM 模型实例的列表。
为什么不像这样对查询进行排序:
ut = Tag.objects.order_by('-count')
解决方案 7:
如果您想要排序的属性是属性,那么您可以避免导入operator.attrgetter
,而使用属性的fget
方法。
例如,对于Circle
具有属性的类,radius
我们可以按半径对列表进行排序,circles
如下所示:
result = sorted(circles, key=Circle.radius.fget)
这不是最著名的功能,但经常可以帮助我节省导入的行数。
解决方案 8:
向对象类添加丰富的比较运算符,然后使用列表的 sort() 方法。
请参阅python 中的丰富比较。
更新:虽然这种方法可行,但我认为 Triptych 的解决方案更适合您的情况,因为它更简单。
解决方案 9:
另外如果有人想对包含字符串和数字的列表进行排序,例如
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)
解决方案 10:
@Jose M Vidal 的回答提到了一些重要的事情:使用丰富的比较(__lt__
如__eq__
@jpp 的回答中的 等)会使排序比传递 key 函数(如接受的答案)慢得多。但是,他们最终展示了一个使用__cmp__
Python 3 中不存在的方法的测试(坦白说,这确实比在 Python 2 中传递 key 慢得多)。
我想指出的是,即使在 Python 3.12.0 中,使用@jpp 的答案中的丰富比较也会使排序比传递关键函数慢得多。
下面显示了一个小型 timeit 测试的结果,其中比较了使用丰富比较、lambda 键函数和作为键的排序。对于包含 10k 个项目的列表,使用丰富比较时大约需要 18.8 毫秒,而使用 lambda 键函数时需要 2.93 毫秒,使用operator.attrgetter
时需要 2.47 毫秒。operator.attrgetter
因此,正如 @tzot 提到的,operator.attrgetter
它比 lambda 更快;但是,首先使用键函数而不是丰富的比较可以使排序速度提高 5 倍以上。
import timeit
import random
from operator import attrgetter
class Card(object):
def __init__(self, rank):
self.rank = rank
def __eq__(self, other):
return self.rank == other.rank
def __lt__(self, other):
return self.rank < other.rank
n = 100
random.seed(0)
lst = [Card(random.randrange(10000)) for _ in range(10000)]
min(timeit.repeat(lambda: sorted(lst), number=n))/n
# 0.018813106999732553
min(timeit.repeat(lambda: sorted(lst, key=lambda card: card.rank), number=n))/n
# 0.0029304770001908763
min(timeit.repeat(lambda: sorted(lst, key=attrgetter('rank')), number=n))/n
# 0.00247172600007616
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件