pythonsort函数和快排哪个快_python的sort函数与cmp参数

你见过驴在麦尖上跑吗?——大咕咕鸡

1.基本用法

描述

sorted() 函数对所有可迭代的对象进行排序操作。

语法

sorted 语法:

sorted(iterable[, cmp[, key[, reverse]]])

复制代码

参数说明:

iterable -- 可迭代对象。

cmp -- 比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。

key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。

reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。

返回值

返回重新排序的列表。

复制代码

2.sort函数中的cmp参数

sort中的key参数使用lambda只能对取出的一个元素操作,两个值时就会报错。

而且在python2.4前,sorted()和list.sort()函数没有提供key参数,但是提供了其他语言都常用的cmp参数来让用户指定比较函数 ,默认值为None,可以传入一个具有两个参数的匿名函数。

不过在python3中为了节省内存已经取消。

本身cmp是一个独立函数:cmp(x ,y) ,当xy会返回正数、当x=y则返回0。

>>> cmp(11,56)

-1

>>> cmp(56,11)

1

>>> cmp(11,11)

0

>>> cmp('abc','b')

-1

复制代码

简单用法有

>>>def numeric_compare(x, y):

return x - y

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

[1, 2, 3, 4, 5]

复制代码

这样看起来好像没什么用,查了许多资料说的也语焉不详,来试一下:

>>>a = [-5, -2, 3, 6]

>>>sorted(a, cmp=lambda x, y: x-y)

>>>a

[-5, -2, 3, 6] # 是正常正序排序

>>>a.sort(cmp=lambda x, y: y -x)

>>>a

[6, 3, -2, -5] # 这是逆序排序

# 好玩的来了~~

>>>a = [-2, -5, 6, 3]

>>>sorted(a, cmp=lambda x, y: -x)

[3, 6, -2, -5]

>>>sorted(a, cmp=lambda x, y: -y)

[-2, -5, 3, 6]

>>>sorted(a,cmp=lambda x, y: x+y)

[-5, -2, 6, 3]

>>>sorted(a,cmp=lambda x, y: x )

[-5, -2, 6, 3]

>>>sorted(a,cmp=lambda x, y: y )

[6, 3, -5, -2]

>>>sorted(a,cmp=lambda x, y: 1 )

[-2, -5, 6, 3]

>>>sorted(a,cmp=lambda x, y: 0)

[-2, -5, 6, 3]

>>>sorted(a,cmp=lambda x, y: -1)

[3, 6, -5, -2]

>>>sorted(a,cmp=lambda x, y: True)

[-2, -5, 6, 3]

>>>sorted(a,cmp=lambda x, y: False)

[-2, -5, 6, 3]

>>>sorted(a,cmp=lambda x, y: None)

Traceback (most recent call last):

File "", line 1, in

TypeError: comparison function must return int, not NoneType

# 啊哦,不能返回空值,但是说可以返回任意int类型

>>>sorted(a,cmp=lambda x, y: 5)

[-2, -5, 6, 3]

>>>sorted(a,cmp=lambda x, y: -2)

[3, 6, -5, -2]

复制代码

可以看出返回True和False得到的结果相同,且与返回1,和0的结果相同,结果不同的是返回非负数和负数:

正数时,按照列表本身的顺序排列;

负数时,按照列表本身顺序的逆序排序,类似于切片步长为-1时。

要研究返回值为“-x”,“-y”,“x+y”等时,为什么会得到那种奇怪的效果,我用了pycharm 的debug来分析。

sorted(a, cmp=lambda x, y: -x),这会创建一个副本,不会改变列表本身,之前用sorted是为了更直观观察各种不同值对列表的影响。

为了观察x,y在每一步的值,所以现在以a.sort(cmp=lambda x, y: -x)为例,整理如下:

可以看出,系统逻辑为,3要排在6之前,6要排在-2之前,而-2要在-5之前,于是得到结果。

过程中,列表a一直为空,最后一步编译器才将排列好的值填进。

至于编译器取出列表中元素依据的是什么顺序就是更底层的原理了,在此不再深究。

最后:

在pytho3中如果想要在sort函数中使用cmp参数,需要从模块导入函数from functools import cmp_to_key,然后在sort将其赋值给key,来看例子:

from functools import cmp_to_key

nums = [1, 3, 2, 4]

nums.sort(key=cmp_to_key(lambda a, b: a - b))

print(nums) # [1, 2, 3, 4]

复制代码

3.sort函数调用Operator模块函数

operator模块有itemgetter,attrgetter,从2.6开始还增加了methodcaller方法。

>>>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),

]

>>>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')) #按列表中对象的“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)]

复制代码

4.python中sort函数的实现原理

C++内部的sort是由快排,直接插入和堆排序混合的,具体详情见STL源码剖析。

当数据量比较大的时候先用的快排,当数据量小的时候用直接插入,因为当数据量变小时,快排中的每个部分基本有序,接近直接插入的最好情况的时间复杂度O(n),就比快排要好一点了。

java内部用的都是归并排序。

因为C++模板有很强的inline优化机制,比较操作相对于赋值(移动)操作要快的多(尤其是元素较大时),而java中的情况正好相反,移动(赋值)一般比比较快;另一方面,一般情况下,归并排序的比较次数小于快速排序的比较次数,而移动次数一般多于快速排序的移动次数,二者大约都是2~3倍的差距。因为这样,java标准库中的一般排序使用的归并排序的一种变种。

python内部的sort采用的是混合(hybrid)排序,规模小的时候采用binary insertion(折半插入排序),规模大的时候采用samplesort(样本排序)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值