Python判断列表是否已排序的各种方法及其性能本节判断列表排序的函数名格式为IsListSorted_XXX() 。为简洁起见,除代码片段及其输出外,一律以_XXX()指代 。
2.1 guess
def IsListSorted_guess(lst):
listLen = len(lst)if listLen = 1:return True
#由首个元素和末尾元素猜测可能的排序规则
if lst[0] == lst[-1]: #列表元素相同
for elem in lst:if elem != lst[0]: return False
elif lst[0]lst[-1]: #列表元素升序
for i, elem in enumerate(lst[1:]):if elemlst[i]: return False
else: #列表元素降序
for i, elem in enumerate(lst[1:]):if elemlst[i]: return False
return True
_guess()是最通用的实现,几乎与语言无关 。值得注意的是,该函数内会猜测给定列表可能的排序规则 , 因此无需外部调用者指明排序规则 。
2.2 sorted
def IsListSorted_sorted(lst):
return sorted(lst) == lst or sorted(lst, reverse=True) == lst
_sorted()使用Python内置函数sorted() 。由于sorted()会对未排序的列表排序,_sorted()函数主要适用于已排序列表 。
若想判断列表未排序后再对其排序,不如直接调用列表的sort()方法 , 因为该方法内部会判断列表是否排序 。对于已排序列表,该方法的时间复杂度为线性阶O(n)——判断为O(n)而排序为O(nlgn) 。
2.3 for-loop
def IsListSorted_forloop(lst, key=lambda x, y: x = y):
for i, elem in enumerate(lst[1:]):#注意,enumerate默认迭代下标从0开始
if not key(lst[i], elem): #if elemlst[i]更快,但通用性差
return False
return True
无论列表是否已排序 , 本函数的时间复杂度均为线性阶O(n) 。注意,参数key表明缺省的排序规则为升序 。
2.4 all
def IsListSorted_allenumk(lst, key=lambda x, y: x = y):
return all(key(lst[i], elem) for i, elem in enumerate(lst[1:]))import operatordef IsListSorted_allenumo(lst, oCmp=operator.le):
return all(oCmp(lst[i], elem) for i, elem in enumerate(lst[1:]))def IsListSorted_allenumd(lst):
return all((lst[i] = elem) for i, elem in enumerate(lst[1:]))def IsListSorted_allxran(lst, key=lambda x,y: x = y):
return all(key(lst[i],lst[i+1]) for i in xrange(len(lst)-1))def IsListSorted_allzip(lst, key=lambda x,y: x = y):
from itertools import izip #Python 3中zip返回生成器(generator),而izip被废弃
return all(key(a, b) for (a, b) in izip(lst[:-1],lst[1:]))
lambda表达式与operator运算符速度相当,前者简单灵活,后者略为高效(实测并不一定) 。但两者速度均不如列表元素直接比较(可能存在调用开销) 。亦即 , _allenumd()快于_allenumo()快于_allenumk() 。
若使用lambda表达式指示排序规则,更改规则时只需要改变x和y之间的比较运算符;若使用operator模块指示排序规则,更改规则时需要改变对象比较方法 。具体地,lt(x, y)等效于xy,le(x, y)等效于x = y,eq(x, y)等效于x == y,ne(x, y)等效于x != y,gt(x, y)等效于xy,ge(x, y)等效于x = y 。例如,_allenumo()函数若要严格升序可设置oCmp=operator.lt 。
此外,由all()函数的帮助信息可知,_allenumk()其实是_forloop()的等效形式 。
2.5 numpy
def IsListSorted_numpy(arr, key=lambda dif: dif = 0):
import numpytry:if arr.dtype.kind == 'u': #无符号整数数组执行np.diff时存在underflow风险
arr = numpy.int64(lst)except AttributeError:pass #无dtype属性,非数组
return (key(numpy.diff(arr))).all() #numpy.diff(x)返回相邻数组元素的差值构成的数组
NumPy是用于科学计算的Python基础包,可存储和处理大型矩阵 。它包含一个强大的N维数组对象,比Python自身的嵌套列表结构(nested list structure)高效得多 。第三节的实测数据表明 , _numpy()处理大型列表时性能非常出色 。
推荐阅读
- 两人竞技体育游戏大全,两人竞技体育游戏大全简单
- 关注宁阳教体局公众号是什么,宁阳教育局投诉电话
- 英文直播话术内衣,英文直播话术内衣怎么说
- vb.net多文档 vbnet word
- 头条视频每天拍什么,头条视频每天拍什么好
- 虚拟同步机的故障保护,虚拟同步机的故障保护有哪些
- 模拟航海驾驶游戏下载安装,模拟航船下载
- 年糕店如何营销,年糕卖点
- 移动服务器负载均衡,负载均衡服务器与服务器如何连接