python的排序方法有两个
1 nums.sort() # 原数组上排序, 没有返回值, nums变为有序 2 # 或者 3 nums = sorted(nums) # 原数组不变, 会返回一个排好序的新数组
那么如何自定义排序规则呢?
自定义排序规则:
假设现在有这么个问题,有n个学生, 每个学生有一个数学成绩,有一个语文成绩,
要求按照总分从高到低排序,分数一样,再按照数学成绩从低到高, 再一样则按照语文成绩从高到低。
这个问题该怎么解决呢?
对于java, 我们有两种方式,一种是自定义Comparator比较器, 另一种是类实现Comparable接口。
首先我们定义一个学生类:
1 class Student: 2 def __init__(self, math, chinese): 3 self.math = math # 数学成绩 4 self.chinese = chinese # 语文成绩 5 6 # 总分 7 def sum(self): 8 return self.math + self.chinese
python实现自定义排序,比较灵活和简单, 因为sort方法可以接受一个key作为参数, 这个key接受一个函数,
这个函数接受一个参数, 返回一个值, 那么最终就是用这个函数返回的值来比较大小, 从而实现排序。
所以想要自定义排序,我们可以传入一个恰当的函数作为key的值。
比如对于上面提出的问题,排序可以这么写:
1 def cmp(e): 2 return (-e.sum(), e.math, -e.chinese) 3 4 students.sort(key=cmp)
首先我们定义一个函数cmp, 这个函数接收一个参数, 返回一个值,并将其赋值给key。
那么对students数组排序,实际上相当于对每个数组元素,被cmp函数作用一遍之后的值进行排序。
也就是相当于是对这些返回的元祖进行排序。 然后观察元祖的返回值, 第一个是-e.sum(), 元祖默认是从小到大按数值大小进行排序的,所有就实现了
对学生数组按总分进行从高到低排序了;总分相同,就按照数学成绩从低到高排序了
完整代码如下:
1 class Student: 2 def __init__(self, math, chinese): 3 self.math = math # 数学成绩 4 self.chinese = chinese # 语文成绩 5 6 # 总分 7 def sum(self): 8 return self.math + self.chinese 9 10 def __str__(self): 11 return "总分:{},数学:{},语文:{}".format(self.sum(), self.math, self.chinese) 12 13 n = int(input()) 14 students = [None for i in range(n)] # 多个Student对象 15 for i in range(n): 16 a, b = map(int, input().split()) 17 students[i] = Student(a, b) 18 19 def cmp(e): 20 return (-e.sum(), e.math, -e.chinese) 21 22 students.sort(key=cmp) 23 print(*students, sep='\n')
测试结果如下:
5 60 70 70 60 80 60 75 90 90 75 总分:165,数学:75,语文:90 总分:165,数学:90,语文:75 总分:140,数学:80,语文:60 总分:130,数学:60,语文:70 总分:130,数学:70,语文:60
对于key函数, 我们都是接受一个参数,返回一个值,所以这个函数往往比较简单,所以可以考虑用lambda表达式
可以改成如下代码:
students.sort(key=lambda e: (-e.sum(), e.math, -e.chinese))
基本上用这种方法可以解决绝大部分排序问题
重载运算符
在java中我们可以实现一个Comparable接口来让对象具备可比较性。在python当中我们可以通过重载运算符的方式来实现对象之间的可比较性。
python中可以重载的运算符:
dir(object) ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__ ', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
通过dir(object)我们可以看到python类当中有很多双下划线开头的方法,这些都是内置方法,有特殊用途。
其中:
__gt__ 对应 大于号 >
__lt__ 对应 小于号 <
__ge__ 对应 大于等于号 >=
__le__ 对应小于等于号 <=
只要重载了其中一个运算符,那么这个类的对象就具备了可比较性
以上文的学生类为例:
完整代码如下:
1 class Student: 2 def __init__(self, math, chinese): 3 self.math = math # 数学成绩 4 self.chinese = chinese # 语文成绩 5 6 # 总分 7 def sum(self): 8 return self.math + self.chinese 9 10 def __lt__(self, other): 11 if self.sum() == other.sum(): 12 if self.math == other.math: 13 return self.chinese > other.chinese 14 else: 15 return self.math < other.math 16 else: 17 return self.sum() > other.sum() 18 19 def __str__(self): 20 return "总分:{},数学:{},语文:{}".format(self.sum(), self.math, self.chinese) 21 22 n = int(input()) 23 students = [None for i in range(n)] # 多个Student对象 24 for i in range(n): 25 a, b = map(int, input().split()) 26 students[i] = Student(a, b) 27 28 students.sort() 29 print(*students, sep='\n')
测试结果如下:
5 60 70 70 60 80 60 75 90 90 75 总分:165,数学:75,语文:90 总分:165,数学:90,语文:75 总分:140,数学:80,语文:60 总分:130,数学:60,语文:70 总分:130,数学:70,语文:60
重载了小于号运算符 < 后, 任意两个学生对象可以直接进行比较 如 : s1 < s2, 其中s1和s2是学生对象。
那么自然就知道如何比较大小了, 这时候sort函数可以不用传入key,也可以按我们的自定义规则排序了
标签:__,chinese,python,self,问题,总分,排序,math From: https://www.cnblogs.com/QWZeng/p/17157415.html