摘要:项目地址提供两种内置排序方法,一个是只针对的原地排序方法,另一个是针对所有可迭代对象的非原地排序方法。
项目地址:https://git.io/pytips
Python 提供两种内置排序方法,一个是只针对 List 的原地(in-place)排序方法 list.sort(),另一个是针对所有可迭代对象的非原地排序方法 sorted()。
所谓原地排序是指会立即改变被排序的列表对象,就像 append()/pop() 等方法一样:
from random import randrange lst = [randrange(1, 100) for _ in range(10)] print(lst) lst.sort() print(lst)
[57, 81, 32, 74, 12, 89, 76, 21, 75, 6] [6, 12, 21, 32, 57, 74, 75, 76, 81, 89]
sorted() 不限于列表,而且会生成并返回一个新的排序后的列表,原有对象不受影响:
lst = [randrange(1, 100) for _ in range(10)] tup = tuple(lst) print(sorted(tup)) # return List print(tup)
[11, 36, 39, 41, 48, 48, 50, 76, 79, 99] (11, 41, 79, 48, 48, 99, 39, 76, 36, 50)
虽然不是原地排序,但如果是传入生成器,还是会被循环掉的:
tup = (randrange(1, 100) for _ in range(10)) print(sorted(tup)) for i in tup: print(i)
[5, 12, 15, 21, 57, 69, 73, 83, 90, 95]Key
对简单的迭代对象进行排序只需要逐次提取元素进行比较即可,如果想要对元素进行一些操作再进行比较,可以通过 key 参数指定一个取值函数。这里的 key 用法很像 0x02 函数式编程提到的 map/filter 所接受的函数,不同之处在于这里的 key 函数只是在排序比较前对元素进行处理,并不会改变元素原本的值,例如我们对一组整数按照(key 可以理解为按照的意思)绝对值进行排序:
lst = [randrange(-10, 10) for _ in range(10)] print(lst) print(sorted(lst, key=abs))
[0, 7, 0, -10, 3, 7, -9, -10, -7, -10] [0, 0, 3, 7, 7, -7, -9, -10, -10, -10]
或者,当迭代对象的元素较为复杂时,可以只按照其中的某些属性进行排序:
lst = list(zip("hello world hail python".split(), [randrange(1, 10) for _ in range(4)])) print(lst) print(sorted(lst, key=lambda item: item[1]))
[("hello", 3), ("world", 3), ("hail", 9), ("python", 9)] [("hello", 3), ("world", 3), ("hail", 9), ("python", 9)]
Python 的 operator 标准库提供了一些操作符相关的方法,可以更方便地获取元素的属性:
from operator import itemgetter, attrgetter print(lst) print(sorted(lst, key=itemgetter(1))) # 一切都只是函数 fitemgetter = lambda ind: lambda item: item[ind] print(sorted(lst, key=fitemgetter(1))) class P(object): def __init__(self, w, n): self.w = w self.n = n def __repr__(self): return "{}=>{}".format(self.w, self.n) ps = [P(i[0], i[1]) for i in lst] print(sorted(ps, key=attrgetter("n")))
[("hello", 3), ("world", 3), ("hail", 9), ("python", 9)] [("hello", 3), ("world", 3), ("hail", 9), ("python", 9)] [("hello", 3), ("world", 3), ("hail", 9), ("python", 9)] [hello=>3, world=>3, hail=>9, python=>9]
经过 key 处理之后会通过 < 符号对两个元素进行比较,在 Python 2.7 的版本中,sorted() 还可以接收另外一个参数 cmp,用来接管 < 的比较过程。但是在 Python 3.5 中已经全面摒弃了这一做法,包括 sorted() 中的 cmp 参数和对象中的 __cmp__ 比较操作,只有在需要向后兼容的时候才可能在 Python 3.5 用到这一功能,其替换的方法为:
from functools import cmp_to_key as new_cmp_to_key # new_cmp_to_key works like this def cmp_to_key(mycmp): "Convert a cmp= function into a key= function" class K: def __init__(self, obj, *args): self.obj = obj def __lt__(self, other): return mycmp(self.obj, other.obj) < 0 return K def reverse_cmp(x, y): return y[1] - x[1] sorted(lst, key=cmp_to_key(reverse_cmp))
[("hail", 9), ("python", 9), ("hello", 3), ("world", 3)]
如果想要按照递减排序,只需要设定参数 reverse = True 即可。
欢迎关注公众号 PyHub!
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/37843.html
摘要:项目地址迭代器与生成器迭代器与生成器是中比较常用又很容易混淆的两个概念,今天就把它们梳理一遍,并举一些常用的例子。生成器前面说到创建迭代器有种方法,其中第三种就是生成器。 项目地址:https://git.io/pytips 迭代器与生成器 迭代器(iterator)与生成器(generator)是 Python 中比较常用又很容易混淆的两个概念,今天就把它们梳理一遍,并举一些常用的例...
摘要:借鉴了中的某些迭代器的构造方法,并在中实现该模块是通过实现,源代码。 项目地址:https://git.io/pytips 0x01 介绍了迭代器的概念,即定义了 __iter__() 和 __next__() 方法的对象,或者通过 yield 简化定义的可迭代对象,而在一些函数式编程语言(见 0x02 Python 中的函数式编程)中,类似的迭代器常被用于产生特定格式的列表(或序列)...
摘要:可以通过一个简单的例子来展示当然,也可以用状态变量的做法来替代总结有人觉得的这些用法违反直觉或者是而非,不值得提倡。 项目地址:https://git.io/pytips 我们都知道 Python 中 else 的基本用法是在条件控制语句中的 if...elif...else...,但是 else 还有两个其它的用途,一是用于循环的结尾,另一个是用在错误处理的 try 中。这原本是 P...
摘要:项目地址本篇主要关于三个常用内置方法,,在语言的设计中,通常的语法操作最终都会转化为方法调用,例如相当于中的描述符就是将对象属性的获取赋值以及删除等行为转换为方法调用的协议例如我们要获取一个对象的属性,可以通过的方式取得而通过的 项目地址:https://git.io/pytips 本篇主要关于三个常用内置方法:property(),staticmethod(),classmethod...
摘要:项目地址中内置的库和分别提供了堆和优先队列结构,其中优先队列本身也是基于实现的,因此我们这次重点看一下。堆可以用于实现调度器例见之协程,更常用的是优先队列例如。 项目地址:https://git.io/pytips Python 中内置的 heapq 库和 queue 分别提供了堆和优先队列结构,其中优先队列 queue.PriorityQueue 本身也是基于 heapq 实现的,因...
阅读 1817·2023-04-26 01:55
阅读 1080·2021-09-30 09:47
阅读 1676·2019-08-30 15:54
阅读 742·2019-08-30 15:53
阅读 694·2019-08-30 15:52
阅读 1135·2019-08-30 15:44
阅读 2412·2019-08-30 14:06
阅读 1059·2019-08-29 16:39