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,也可以按我们的自定义规则排序了

python的排序问题的更多相关文章

  1. Python字典排序问题

    字典的问题 navagation: 1.问题来源 2.dict的学习 *3.numpy的应用 1.问题来源 在做cs231n,assigment1-kNN实现的时候,需要对一个列表中的元素进行计数,并 ...

  2. Python中的各种排序问题

    小书匠python排序 本章目录,快速浏览所需内容: 基本的排序 1.列表(list) 1.1按列表元素大小排序 1.2按列表元素的属性 2.字典(dictory) 3.元组(tuple)排序 3.1 ...

  3. Python中os.listdir的排序问题

    上周应别人要求,使用python批量修改文件名称.文件名有规律,当时就用了一个函数直接精确的用文件名替换了.后来想直接可以用listdir来遍历每个文件来修改更加通用一些.但是看了os.listdir ...

  4. 对Python中函数参数类型及排序问题,三个方面的总结

    Python中函数的参数问题有点复杂,主要是因为参数类型问题导致的情况比较多,下面来分析一下. 参数类型:缺省参数,关键字参数,不定长位置参数,不定长关键字参数. 其实总共可以分为 位置参数和关键字参 ...

  5. python基础知识-列表的排序问题

    def main(): f=['orange','zoo','apple','internationalization','blueberry'] #python 内置的排序方式默认为升序(从小到大) ...

  6. python 列表、字典多排序问题

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/justin051/article/det ...

  7. python 层次索引交换级别以及排序问题

  8. python 中各种数据类型的排序问题

    list #按照list的第二键值排序 disP2P = [[1,2,3],[2,3,4],[4,5,6]] disP2P = sorted(disP2P,key = lambda x:x[2]) s ...

  9. Python从破门而入到夺门而出

    MD版网盘备份: 链接: https://pan.baidu.com/s/1kVJNRSz 密码: agxt 基于<简明Python教程> 一.Python概览 1.使用PyCharm是非 ...

  10. python面试大全

    问题一:以下的代码的输出将是什么? 说出你的答案并解释. class Parent(object): x = 1 class Child1(Parent): pass class Child2(Par ...

随机推荐

  1. 自己动手从零写桌面操作系统GrapeOS系列教程——6.电脑启动过程介绍

    学习操作系统原理最好的方法是自己写一个简单的操作系统. 按一下电脑上的电源按钮,电脑就启动了,不一会儿电脑屏幕上就出现了登录界面或直接进入了桌面. 这是一个很日常的场景,但有时候会有个疑问:电脑内部是 ...

  2. RocketMQ - 消费者进度保存机制

    RocketMQ设计了远程位点管理和本地位点管理两种位点管理方式.集群消费时,位点由客户端提交给Broker保存,具体实现代码在RemoteBrokerOffsetStore.java文件中:广播消费 ...

  3. STM32 I2C介绍和软件模拟I2C编程要点

    I2C协议层独特特征: 1. 通过地址(Master/Slave Address)区分不同的设备. 2. ACK信号体制,即通过ACK表示是否进行继续传输. 3.由SCL.SDA的四种关系,映射数据有 ...

  4. CF1768F 题解

    题意 传送门 给定长度为 \(n\) 的序列 \(a\),求序列 \(f\),满足: \[f_i= \begin{equation} \begin{cases} 0&(i=1)\\ \min\ ...

  5. ORM框架——Dapper

    1.什么是ORM ORM(Object Relational Mapping)对象关系映射,是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术,用于实现面向对象编程语言里不同类型系统的数据之 ...

  6. docker swarm集群安装使用

    1.安装master docker swarm init --advertise-addr 10.98.10.186 Swarm initialized: current node (qemrm3oq ...

  7. vue 事件传递原始 DOM 事件

    vue 事件传递原始 DOM 事件 在事件传参中传递特殊变量 $event @click= "warn('1', $event)"

  8. IDEA激活 重置试用30天

    转载于 https://www.cnblogs.com/renlywen/p/14216325.html jetbrains-agent已经停止,现在又出现了新的激活方式,重置试用时间,以下为操作步骤 ...

  9. VUE学习-插槽

    插槽 匿名插槽 子组件设置匿名插槽 <script type="text/x-template" id="custom-comp"> <div ...

  10. # HUAWEI--IPv6 over IPv4隧道配置(简单案例)

    HUAWEI--IPv6 over IPv4隧道配置(简单案例) 拓扑图 项目要求: PC3和PC4使用的IPv6的地址,路由和路由器之间的连接使用IPv4的地址并使用静态路由连接,路由器和PC机的连 ...