排序的技术
装饰 - 排序 - 去装饰¶
装饰 - 排序 - 去装饰 (Decorate-Sort-Undecorate) 得名于它的三个步骤:
首先,用控制排序顺序的新值装饰初始列表。
其次,排序装饰后的列表。
最后,去除装饰即得按新顺序排列的初始值的列表。
例如,用 DSU 方法按 grade 排序学生数据:
>>> decorated = [(student.grade, i, student) for i, student in enumerate(student_objects)]
>>> decorated.sort()
>>> [student for grade, i, student in decorated] # 取消装饰
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
这个方法之所以有效是因为元组按字典顺序进行比较,先比较第一项;如果它们相同则比较第二个项目,依此类推。
不一定在所有情况下都要在装饰列表中包含索引 i ,但包含它有两个好处:
排序是稳定的——如果两个项具有相同的键,它们的顺序将保留在排序列表中。
原始项目不必具有可比性,因为装饰元组的排序最多由前两项决定。因此,例如原始列表可能包含无法直接排序的复数。
这个方法的另一个名字是 Randal L. Schwartz 在 Perl 程序员中推广的 Schwartzian transform.
既然 Python 排序提供了键函数,那么通常不需要这种技术。