• python list 自定义排序


    我们都知道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))
    
  • 相关阅读:
    mysql慢查询日志
    VS中MFC连接MySQL的方法【转】
    localtime函数时区问题
    gethostbyname()函数【转】
    剪切板操作
    C/C++字符串查找函数 【转】
    vs2013出现IntelliSense错误,但是错误又不影响使用的消除办法
    c语言基础精讲加实例(个人觉得复习基础挺好的,)
    vs2013下qt工程调用自建的lib库函数教程
    取出16进制位对应位数的数字是0还是1(C语言)
  • 原文地址:https://www.cnblogs.com/interdrp/p/15580130.html
Copyright © 2020-2023  润新知