Contents
30.2.4. 使用sort来表示复杂的排序¶
列表类型提供了叫sort的方法,可以根据多项指标给list实例中的元素排序。默认按照升序排序。
In [62]: numbers = [93, 86, 11, 68, 70]
In [63]: numbers.sort()
In [64]: print(numbers)
[11, 68, 70, 86, 93]
那么,一般对象该如何排序呢?比如定义以Tool类表示各种建筑工具,它带有__repr__方法:
In [1]: class Tool:
...: def __init__(self, name, weight):
...: self.name = name
...: self.weight = weight
...:
...: def __repr__(self):
...: return f'Tool({self.name!r}, {self.weight})'
...:
...: tools = [
...: Tool('level', 3.5),
...: Tool('hammer', 1.25),
...: Tool('screwdriver', 0.5),
...: Tool('chisel', 0.25),
...: ]
...:
...:
In [2]: print('Unsorted:', repr(tools))
Unsorted: [Tool('level', 3.5), Tool('hammer', 1.25), Tool('screwdriver', 0.5), Tool('chisel', 0.25)]
In [3]: tools.sort(key=lambda x: x.name)
In [4]: print('\nSorted: ', tools)
Sorted: [Tool('chisel', 0.25), Tool('hammer', 1.25), Tool('level', 3.5), Tool('screwdriver', 0.5)]
如果想改用另一项标准,比如用weight来排序,那只需要再定义一个lambda函数:
In [5]: tools.sort(key=lambda x: x.weight)
...: print('By weight:', tools)
...:
...:
By weight: [Tool('chisel', 0.25), Tool('screwdriver', 0.5), Tool('hammer', 1.25), Tool('level', 3.5)]
对于字符串这样的基本类型,我们可能需要通过key函数先对它的内容做一些变换,并根据变换之后的结果来排序。
In [6]: places = ['home', 'work', 'New York', 'Paris']
...: places.sort()
...: print('Case sensitive: ', places)
...: places.sort(key=lambda x: x.lower())
...: print('Case insensitive:', places)
...:
...:
Case sensitive: ['New York', 'Paris', 'home', 'work']
Case insensitive: ['home', 'New York', 'Paris', 'work']
要点:
列表的sort方法可以根据自然顺序给其中的字符串、整数、元组等内置类型的元素进行排序。
普通对象如果通过特殊方法定义了自然顺序,那么也可以用sort方法来排列,但这样的对象并不多见。可以把辅助函数传给sort方法的key参数,让sort根据这个函数所返回的值来排列元素顺序,而不是根据元素本身来排列。
如果排序时要依据的指标有很多项,可以把它们放在一个元组中,让key函数返回这样的元组。
对于支持一元减操作符的类型来说,可以单独给这项指标取反,让排序算法在这项指标上按照相反的方向处理。
如果这些指标不支持一元减操作符,可以多次调用sort方法,并在每次调用时分别指定key函数与reverse参数。
最次要的指标放在第一轮处理,然后逐步处理更为重要的指标,首要指标放在最后一轮处理。