python list 自定义排序

python

我们都知道python中有两种排序的方法,
原地排序的x.sort(),和不改变原列表有返回值的sorted(x)
自定义排序函数

先不关心其实原地排序还是有返回值的排序,研究其内部的排序原理,其内部是根据什么排序的呢,默认的排序方法是内建的cmp函数
对于cmp(x,y):

# 比较器:按目录的深度倒序显示

def tcmp(a,b):

if len(a.split(\'\\\')) > len(b.split(\'\\\')) :

return -1

elif len(a.split(\'\\\')) < len(b.split(\'\\\')) :

return 1

else:

return 0

 
如果想要x排在y前面那么返回一个负数,如果想x排在y后面那么返回一个正数

根据这个原理我们可以自定义一些排序函数compare_personal,并将这个函数传入sort或sorted方法中。
python2中,用关键字cmp直接传入即可,

a = [1,2,4,3,5]

def compare_personal:

pass

a.sort(cmp=compare_personal)

sorted(a,cmp=compare_personal)


而在python3中,cmp关键字被移除了,这样的写法就无法运行了,需要借助functools包来完成

a = [1,2,4,3,5]

def compare_personal(x,y):

pass

a.sort(key= functools.cmp_to_key(compare_personal))

c = sorted(b, key=functools.cmp_to_key(compare_personal))

好了,知道如何使用以后就可以构建自定义的排序函数,比如们要对一个数组进行排序,排序的依据是元素mode7后的大小,按照升序排列,我们可以电泳仪排序函数如下

import  functools

a = [3,8,14,6,7]

def compare_personal(x,y):

return x%7-y%7

a.sort(key=functools.cmp_to_key(compare_personal))

b = sorted(a,key=functools.cmp_to_key(compare_personal))

print(a)

print(b)

>>>[14, 7, 8, 3, 6]

>>>[14, 7, 8, 3, 6]

按照某一元素进行排序

加入我们有下面的数据,列表中都是元组,我们想根据元组中的某些元素进行排序。
元组中的三个元素分别表示姓名,班级和年龄

students = [("zhangsan","A",10),("lisi","C",9),("lisi1","A",9),("lisi2","B",9),("wangwu","B",13)]

我们只需要把要排序的元素通过lamada 表达式返回即可,

students.sort(key=lambda x:(x[2],x[1]))

print(students)

>>[(\'lisi1\', \'A\', 9), (\'lisi2\', \'B\', 9), (\'lisi\', \'C\', 9), (\'zhangsan\', \'A\', 10), (\'wangwu\', \'B\', 13)]

返回一个很好理解,就是根据那一个元素进行排序,上面的代码中返回了两个元素,也就是数据中x[2]相同的数据会根据x[1]再排个序
如果是对象的话也是一个道理,lamada返回对象中要排序的属性名称即可

class student:

def __init__(self,name,age,weight):

self.name = name

self.age = age

self.weight = weight

std1 = student("std1",10,55)

std2 = student("std2",8,30)

std3 = student("std3",11,65)

std4 = student("std4",9,50)

students = [std1,std2,std3,std4]

students.sort(key= lambda x:x.age)

for std in students:

print(std.name)

>>>

std2

std4

std1

std3

利用Operator 模块指定排序元素
上面我们说了两种情况,一个是排序元组要通过下标来指定要被排序的元素,第二种是排序对象,要通过指定属性名来指定排序依据的属性。Operator模块的attrgetter和itemgetter
itemgetter可用来指定下标
attrgetter可用来指定属性名

import operator

students = [("zhangsan","A",10),("lisi","C",9),("lisi1","A",9),("lisi2","B",9),("wangwu","B",13)]

students.sort(key=operator.itemgetter(2))

print(students)

>>>

[(\'zhangsan\', \'A\', 10), (\'lisi1\', \'A\', 9), (\'lisi2\', \'B\', 9), (\'wangwu\', \'B\', 13), (\'lisi\', \'C\', 9)]

 

import  operator

class student:

def __init__(self,name,age,weight):

self.name = name

self.age = age

self.weight = weight

std1 = student("std1",10,55)

std2 = student("std2",8,30)

std3 = student("std3",11,65)

std4 = student("std4",9,80)

students = [std1,std2,std3,std4]

students.sort(key= operator.attrgetter("weight"))

for std in students:

print(std.name)

>>>

std2

std1

std3

std4

 

import functools

def tcmp(a,b):

if a > b :

return -1

elif a < b :

return 1

else:

return 0

nums = [1,2,3,4]

sorted_nums = sorted(nums, key = functools.cmp_to_key(tcmp))

Note:
    functools.cmp_to_key() 将 cmp函数 转化为 key。
    cmp函数的返回值 必须为 [1,-1,0]
eg:

import functools

def cmpele(a, b):

stra = str(a)

strb = str(b)

stra_len = len(stra)

strb_len = len(strb)

max_len = max(stra_len, strb_len)

i = 0

while i < max_len:

if i < stra_len:

sa = int(stra[i])

elif i == stra_len:

sa = max(int(stra[0]), int(stra[i-1]))

if i < strb_len:

sb = int(strb[i])

elif i == strb_len:

sb = max(int(strb[0]), int(strb[i-1]))

if sa > sb:

return -1

elif sa < sb:

return 1

i += 1

return 0

class Solution:

def largestNumber(self, nums):

"""

:type nums: List[int]

:rtype: str

"""

nums = sorted(nums,key=functools.cmp_to_key(cmpele))

res = ""

for ele in nums:

res += str(ele)

while len(res) > 1 and res[0] == \'0\':

res = res[1:]

return res

nums = [3,30,34,5,9]

print(Solution().largestNumber(nums))

 

以上是 python list 自定义排序 的全部内容, 来源链接: utcz.com/z/387990.html

回到顶部