假设有这样一个问题:
对[[15, 1], [14, 2], [13, 3], [12, 4]]
按照第二元素进行非递增排序。
由于数据是个列表,所以可以使用list
自带的sort()
函数,也可以使用通用的sorted()
函数。
但是最关键的问题在于,如何指定采用第二个元素进行排序。
有如下三种方案:
# 方案1
l = [[15, 2], [14, 4], [13, 6], [12, 8]]
l.sort(key=lambda elem:elem[1], reverse=True)
# 方案2
from operator import itemgetter
l = [[15, 2], [14, 4], [13, 6], [12, 8]]
l = sorted(l, key=itemgetter(1), reverse=True)
# 方案3
l = [[15, 2], [14, 4], [13, 6], [12, 8]]
l = sorted(l, key=lambda elem:elem[1], reverse=True)
这三种方案都是采用了元素本身携带的属性进行排列,都可以完成任务,但有些情况需要实现自定义排序方案,该排序元素并非元素本身的属性,例如要按列表内元素的和进行排序,即期望的结果为:
[[12, 8], [13, 6], [14, 4], [15, 2]]
因为12+8 > 13+6 > 14+4 > 15+2。
两种方案:
# 方案1
import functools
def cmp_func(a, b):
if a > b:
return -1
elif a < b:
return 1
else:
return 0
l = [[15, 2], [14, 4], [13, 6], [12, 8]]
l = sorted(l, key=functools.cmp_to_key(cmp_func), reverse=True)
# 方案2
class LargerNumKey(list):
def __lt__(x, y):
return x[0]+x[1] < y[0]+y[1]
l = [[15, 2], [14, 4], [13, 6], [12, 8]]
l = sorted(l, key=LargerNumKey, reverse=True)
在方案1中,采用了一种比较熟知的方案,自定义cmp
函数,注意的是如果a>b
返回值应该是-1
,a<b
返回值应该是1
。熟悉cpp
的就应该发现,和cpp
的cmp
函数是正好反着的,但又恰好和greater
和less
这样的函数对象又是一致的。
在方案2中,就类似cpp
中采用operator
重载比较符号的方法了。要注意的点在于,这个类要集成自,输入对象,也就是要比较的数据对象类型;其次,在__lt__
中重定义了小于号。
另:
- 当自定义类中两个方法都定义了时,“<”、“>”分别调用
__lt__
和__gt__
方法; - 当自定义类中定义了
__lt__
方法,未定义__gt__
方法时,进行”>”比较也是调用__lt__
方法,只是对调用值求反; - 当自定义类中定义了
__gt__
方法,未定义__lt__
方法时,进行”<”比较也是调用__gt__
方法,只是对调用值求反。