Python 排序 - 对象列表

36 投票
4 回答
43008 浏览
提问于 2025-04-15 19:45

我想如果可以的话,使用 somelist.sort() 这个方法来实现这个功能。

我有一个列表,里面包含一些对象,这些对象都有一个叫 resultType 的成员变量,它是一个整数。我想用这个数字来对列表进行排序。

我该怎么做呢?

谢谢!

4 个回答

1
somelist.sort(cmp = lambda x, y: cmp(x.resultType, y.resultType))

比起下面的方式,这种方式更好:

somelist.sort(key = lambda x: x.resultType)

在第一种情况下,我们传入一个比较函数,用来逐个比较列表中的元素。而在第二种情况下,我们先创建一个新的列表,这个列表包含了通过关键函数得到的结果和原始值的配对。然后我们对这个新列表进行排序,最后再从配对中去掉关键值。如果你的比较函数比较复杂,这样做非常有用,但如果比较函数很简单,这样就浪费内存了。

也就是说,关键版本的展开大致是这样的:

l = [y for x,y in sorted(zip([key(i) for i in l], l))]

对于一个简单的关键函数,这样做显然太繁琐了,所以我建议使用更轻便的基于函数的排序方式。

需要注意的是,cmp函数的返回值需要在小于、等于和大于的情况下分别返回-1、0和1。你可以自己写这个函数,但也可以使用内置的cmp函数,这样会更清晰。

11

当然,你不一定非得用lambda(匿名函数)。任何传入的函数,比如下面这个,也可以用。

def numeric_compare(x, y):
   if x > y:
      return 1
   elif x == y:
      return 0
   else:  #x < y
      return -1

a = [5, 2, 3, 1, 4]
a.sort(numeric_compare)

来源:Python 排序

所以,在你的情况下……

def object_compare(x, y):
   if x.resultType > y.resultType:
      return 1
   elif x.resultType == y.resultType:
      return 0
   else:  #x.resultType < y.resultType
      return -1

a.sort(object_compare)

刚才提到的lambda确实是最简洁的写法,但你也可以使用operator.itemgetter

import operator
#L = [('c', 2), ('d', 1), ('a', 4), ('b', 3)]
map(operator.itemgetter(0), L)
#['c', 'd', 'a', 'b']
map(operator.itemgetter(1), L)
#[2, 1, 4, 3]
sorted(L, key=operator.itemgetter(1))
#[('d', 1), ('c', 2), ('b', 3), ('a', 4)]

所以你可以用itemgetter('resultType')。假设getitem已经定义过了。

sorted(L, key=operator.itemgetter('resultType'))
74
somelist.sort(key = lambda x: x.resultType)

这里有另一种常见的方法来做同样的事情:

import operator
s.sort(key = operator.attrgetter('resultType'))

如果你还没看过的话,可能还想了解一下 sorted。这个方法不会改变原来的列表,而是会返回一个新的已排序的列表。

撰写回答