升序排序学生数据,只需先用
2026/9/7 22:35:06 网站建设 项目流程

Dalke 与

发布版本:

0.1

具备内置特性的列表途径方式, 会在原本的位置上对列表作出修改, 然而, 拥有内置性质的函数, 却是通过可进行迭代的对象去创建出有顺序的列表。

在本文档中,我们将探索使用 对数据进行排序的各种技术。

排序的基础知识

平常的升序排列极为简单: 仅仅只需调用函数, 其返回全新的有序列表。

>>> sorted([5, 2, 3, 1, 4]) [1, 2, 3, 4, 5]

亦能够采用 方式, 它于原处变动原本的列表, 并且返回 None 用以防止产生混淆, 通常来讲比不上方便, 然而要是不需要原本的列表, 运用它会稍微高效一些。

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

又一个不同之处在于 , 方法单独是为列表界定的 , 然而函数接纳任何能够进行迭代的对象结尾要有句号。

>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'}) [1, 2, 3, 4, 5]

键函数

和, 皆存在 key 形参用以指定, 在比较之前, 要对每个列表元素调用的函数, (或是其他, 可调用对象)。

例如,这是个不区分大小写的字符串比较:

>>> sorted("This is a test string from Andrew".split(), key=str.lower) ['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']

形参 key 的值得是那种一元函数(或者是其他能被调用的对象), 它返回的值拿过来用于排序。这速度很快, 为啥呢, 是因为那个键函数只需要在输入的每一个记录之上调用刚刚好一次。

常见的模式是用对象的某一些索引作为键对复杂对象排序。例如:

>>> student_tuples = [ ... ('john', 'A', 15), ... ('jane', 'B', 12), ... ('dave', 'B', 10), ... ] >>> sorted(student_tuples, key=lambda student: student[2]) # sort by age [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

同样的方法对于有具名属性的对象也适用。例如:

>>> class Student: ... def __init__(self, name, grade, age): ... self.name = name ... self.grade = grade ... self.age = age ... def __repr__(self): ... return repr((self.name, self.grade, self.age)) >>> student_objects = [ ... Student('john', 'A', 15), ... Student('jane', 'B', 12), ... Student('dave', 'B', 10), ... ] >>> sorted(student_objects, key=lambda student: student.age) # sort by age [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

模块函数

上面所呈现的键函数模式极为司空见惯, 所以, 赋予了便利功用, 致使访问器机能越发简便、愈发迅速。模块具备、和函数。

用了那些函数之后,前面的示例变得更简单,运行起来也更快:

>>> from operator import itemgetter, attrgetter >>> sorted(student_tuples, key=itemgetter(2)) [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)] >>> sorted(student_objects, key=attrgetter('age')) [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

诸如以 grade 为依据进行排序, 之后再凭借 age 展开分类这样的操作, 运算符模块内所包含的函数能够被用于达成多级排序。

>>> sorted(student_tuples, key=itemgetter(1,2)) [('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)] >>> sorted(student_objects, key=attrgetter('grade', 'age')) [('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

升序与降序

用于与之关联的, 是接受布尔形参, 该形参的作用在于标记降序排序。举例来说, 存在这样一种情况, 即把学生数据依据age进行倒序排序:

>>> sorted(student_tuples, key=itemgetter(2), reverse=True) [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)] >>> sorted(student_objects, key=attrgetter('age'), reverse=True) [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

排序稳定性与复杂排序

排序保证 :等键记录保持原始顺序。

>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)] >>> sorted(data, key=itemgetter(0)) [('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]

留意蓝色的两条记录是怎样维持顺序的: 蓝色, 一, 确保比蓝色, 二来的更早。

借助这特性来凭借相当的一系列排序步达成构建让那复杂排序得以成为可能, 这特性相当了不起。比如说, 若要针对学生数据依照grade降序之后再按照age升序来进行排序, 那么仅仅只需先以age进行排序而后再运用grade进行排序便可达成:

>>> s = sorted(student_objects, key=attrgetter('age')) # sort on secondary key >>> sorted(s, key=attrgetter('grade'), reverse=True) # now sort on primary key, descending [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

能够被抽象成为包装函数, 依赖于接收到的一些字段序的元组对接收回来的列表进行多趟排序。

>>> def multisort(xs, specs): ... for key, reverse in reversed(specs): ... xs.sort(key=attrgetter(key), reverse=reverse) ... return xs >>> multisort(list(student_objects), (('grade', True), ('age', False))) [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

中的曾被使用过的算法, 借助数据集中任何早已存在的有序性, 来高效地进行多种排序。

装饰-排序-去装饰

装饰-排序-去装饰 (-Sort-) 得名于它的三个步骤:

例如,用 DSU 方法按 grade 排序学生数据:

>>> decorated = [(student.grade, i, student) for i, student in enumerate(student_objects)] >>> decorated.sort() >>> [student for grade, i, student in decorated] # undecorate [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

这个方法语之所以有效, 是由于元组依照字典顺序予以比较, 首先会比较第一项, 要是它们相同的话, 就会去比较第二个项目, 依照这样类推下去。

并非在全部情形之下都必然要于装饰的列表当中纳入索引 i , 然而将其纳入存在着两个方面的益处。

这一方法,还有另外一个名字, 它是在诸多 Perl 程序员里头被推广起来 , 叫做 L.。

既然 排序提供了键函数,那么通常不需要这种技术。

比较函数

跟返回一个用于排序的绝对值的键函数不一样, 比较函数是去计算两个输入的相对排序。

例如, 有一个天平, 它会对两个样本进行比较, 且会给出一个相对排序结果, 具体为: 较轻、相等或者较重这类情况。类似地, 存在一个比较函数, 就像 cmp(a, b) 这样, 它会返回一个值, 若此值为负值, 那就表示小于, 若为零, 则表示相等, 要是为正值, 便表示大于。

在从别的语言进行转写算法之际, 常常会碰到比较函数, 除此之外, 有些库会将比较函数当作其API之中的一部分来予以提供, 象这样, 此乃比较函数。

以适应这般情形, 加以供给之处, 存有用于包裹比较函数使之能够当作键函数予以运用的情况:。

sorted(words, key=cmp_to_key(strcoll)) # locale-aware sort order

杂项说明

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询