用 Python 排序数据的多种方法

发布时间:2017-09-07 13:40:23
用 Python 排序数据的多种方法

【Python HOWTOs系列】排序

Python 列表有内置就地排序的方法 list.sort(),此外还有一个内置的 sorted() 函数将一个可迭代对象(iterable)排序为一个新的有序列表。

本文我们将去探索用 Python 做数据排序的多种方法。

排序基础

简单的升序排序非常容易:只需调用 sorted() 函数,就得到一个有序的新列表:

你也可以使用 list.sort() 方法,此方法为就地排序(并且返回 None 来避免混淆)。通常来说这不如 sorted() 方便——但是当你不需要保留原始列表的时候,这种方式略高效一些。

另外一个区别是 list.sort() 方法只可以供列表使用,而 sorted() 函数可以接受任意可迭代对象(iterable)。

Key 函数

list.sort() 和 sorted() 都有一个 key 参数,用于指定在作比较之前,调用何种函数对列表元素进行处理。 For example, here’s a case-insensitive string comparison: 例如,忽略大小写的字符串比较:

key 参数的值应该是一个函数,该函数接收一个参数,并且返回一个 key 为排序时所用。这种方法速度很快,因为每个输入项仅调用一次 key 函数。

一种常见模式是使用对象的下标作为 key 来排序复杂对象。例如:

用 Python 排序数据的多种方法

同样的技巧也可以用在带有命名属性(named attributes)的对象上。例如:

用 Python 排序数据的多种方法

用 Python 排序数据的多种方法

上述的 key 函数模式是非常常见的,所以 Python 提供了一些更简单快速的访问属性的函数。operator 模块有 itemgetter()、attrgetter() 和 methodcaller() 函数。 Using those functions, the above examples become simpler and faster: 使用这些函数,可以使上述的示例更加简洁高效:

operator 模块方法允许多级排序。例如,可以先按 grade 排序,然后再按 age 排序:

list.sort() 和 sorted() 都有布尔型的 reverse 参数,用来指定是否降序。例如,按 age 的降序来对学生数据进行排序:

排序是保证为稳定的,也就是说,当多条记录拥有相同的 key 时,原始的顺序会被保留下来。

注意到两条 blue 记录保持了原来的顺序, 所以 (‘blue’, 1) 一定在 (‘blue’, 2) 之前。

这个非常棒的属性允许你通过一系列排序来进行复杂排序。例如,学生数据先按 grade 升序,然后按 age 降序,优先排序 age,然后再按 grade 排序:

Python 使用的 Timsort 算法由于可以有效利用数据集中已有的顺序,因而可以高效地进行多级排序。

使用 Decorate-Sort-Undecorate 的旧方法

Decorate-Sort-Undecorate 的名称来源于这种方法的三个步骤:

第一步,初始的列表进行转换,获得用于排序的新值。

第二步,将转换为新值的列表进行排序。

最后,还原数据并得到一个排序后仅包含原始值的列表。

例如,使用 DSU(译注:Decorate-Sort-Undecorate的简写)方法,按 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)]

这一方法利用了元组按字典序 (lexicographically) 比较的特性;先比较第一项;如果第一项相同,则比较第二项,以此类推。

在很多情况下是不需要在处理后的列表(decorated list)包含原始下标 i,但是包含原始下标有两个好处:

排序是稳定的——如果有两项有相同的 key,排序后的列表会保留他们的顺序。

原始项不需要是可比较的,因为处理后的元组最多使用前面两项就可以决定排序。例如,原始列表中包含无法直接比较的复数。

这个方法还有另外一个名字,是以 Randal L. Schwartz 的名字来命名的 Schwartzian 变换,因为他使得这个变换在 Perl 程序员中得以流行。

在 Python 排序提供 key 函数之后,这个技巧已经不常用了。

使用 cmp 参数的旧方法

企业建站2800元起,携手武汉肥猫科技,做一个有见地的颜值派!更多优惠请戳:咸宁网站制作 http://xianning.666rj.com


友情链接

独家出品

新闻由机器选取每5分钟自动更新

新闻搜索源于互联网新闻网站和频道,系自动分类排列,本站不刊登或转载任何完整的新闻内容