首页 > 编程语言 >python的排序问题

python的排序问题

时间:2023-02-26 20:58:02浏览次数:37  
标签:__ chinese python self 问题 总分 排序 math

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

相关文章

  • 第一周 python数据分析与挖掘技术实战 第三章
    总结 ............. 图3-1 importpandasaspdcatering_sale='catering_sale.xls'data=pd.read_excel(catering_sale,index_col=u'日期')print(data.descri......
  • python数据分析画图
    importnumpyasnpimportpandasaspdimportmatplotlib.pyplotaspltpath='./data/catering_sale.xls'data=pd.read_excel(path,index_col=u'日期')#读取......
  • python数据分析
    -*-coding:utf-8-*-#代码3-1使用describe()方法即可查看数据的基本情况importpandasaspdcatering_sale='../data/catering_sale.xls'#餐饮数据data=p......
  • python数据分析
    #-*-coding:utf-8-*-"""SpyderEditorThisisatemporaryscriptfile."""importpandasaspdfrommatplotlibimportpyplotasplt##读取数据url=r"F:\data\ca......
  • VSCode写代码时,某些字符高亮问题
    如下图: 解决方法:如下图,在设置中取消“editor.unicodeHighlight.ambiguousCharacters”该选项勾选状态即可:  ......
  • 03:成绩排序
     描述给出班里某门课程的成绩单,请你按成绩从高到低对成绩单排序输出,如果有相同分数则名字字典序小的在前。输入第一行为n(0<n<20),表示班里的学生数目;接下来的n行,......
  • ECharts 图例不正常换行问题
    问题今日发现之前写的图表组件出现了不正常换行的bug,明明画布高度足够,却分成了两行:解决原因是接口返回的数据中出现了脏数据,中间有一条数据name为null,从而导致换行:解......
  • 应用Python进行统计数据画图
     画饼图:#-*-coding:utf-8-*-"""SpyderEditorThisisatemporaryscriptfile."""importpandasaspdimportnumpyasnp#importseabornasimportmatplotli......
  • [oeasy]python0094_视频游戏_双人网球_pong_atari_mos_6502_雅达利_米洛华
    编码进化回忆上次内容上次我们回顾了微软之前的比尔盖茨和保罗艾伦mits迎来的是帮手还是隐患?intel-8080遇到了mos-6502底层硬件驱动游戏行业......
  • 24.生产环境中对不同时区问题的处理办法
    1.current_date,current_timestamp,localtimestamp--1.在会话中修改时区--偏移量-tz_offset--数据库时区--time_zone--系统本地时区--local--区域名--v$timezone_name......