文章目录
- 一个参数比较
- 多个参数比较
在c/c++中,遇到结构体排序类似的问题时可以直接用struct定义一个结构体,然后重写cmp函数实现结构体排序,而在python中,没有结构体,那么如何实现结构体排序?
在python中,列表有两种排序方式,分别是sort和sorted。
- sort是列表的内置方法,可以直接调用,会修改原列表并排好序默认升序,可以通过reverse=True实现降序。cmp函数是比较方法,在python3中已经被废除,key可以指定比较的参数,一维列表一般不需要写key。
list.sort(cmp=None, key=None, reverse=False)
- sorted会新建一个排序好的列表并返回,默认升序,可以通过reverse=True实现降序。同样cmp在python3中已经被废除,key可以指定比较的参数。
sorted(iterable, cmp=None, key=None, reverse=False)
下面介绍如何实现类似于c/c++中的结构体排序。
结构体就是自定义的数据类型,在一个结构体中可以存储任意类型数据。
而列表中可以存储任意类型的数据,可以用一个二维列表充当结构体。
一个参数比较
第一种情况,例如将姓名和成绩作为一个列表保存至一个二维列表中,输入每个学生的姓名和成绩,按照学生成绩降序排除,这种情况可以使用sort函数中的key来指定比较的参数。
①写一个getKey方法
def getKey(x):
return int(x[1])
②调用sort函数时,将getKey函数传入
def getKey(x): # 按照下标为1的元素进行排序
return int(x[1])
N=int(input())
list=[]
for i in range(N):
item=input().split() #输入姓名和成绩
list.append(item)
list.sort(key=getKey,reverse=True)
print(list)
也可以用lambda表达式来写
# 表示按x[1]升序排序
list.sort(key=lambda x:x[1])
下面这个题目就可以使用这种方法来做
第K名
刚举行的万米长跑活动中,有 NNN 个人跑完了全程,所用的时间都不相同。颁奖时为了增加趣味性,随机抽了一个数K,要奖励第 K 名一双跑鞋。
现在组委会给你 N 个人的姓名、成绩(用时,单位是秒),请你编程快速输出第 K 名的姓名。输入格式:
第一行:2 个整数 N 和 K。
下面 N 行:每行第 1个是字符串表示姓名;第 2 个是个整数,表示这个人跑完的使用时间。
输出格式:
一行,第 K 名的姓名。
代码:
def getKey(x):
return int(x[1])
N,K=map(int,input().strip().split())
list=[]
for i in range(N):
item=input().split()
list.append(item)
list.sort(key=getKey)
# 下边是lambda表达式写法
# list.sort(key=lambda x:int(x[1]))
print(list[K-1][0])
多个参数比较
第二种情况比如,列表中有三个数据,首先比较第一个数据,如果第一个数据相等,那么比较第二个,以此类推,这时,通过指定key就无法实现排序了,就必须写一个cmp函数来实现,但是python3又将cmp函数废除了,这时可以通过functools库下的cmp_to_key来实现,然后调用sort时将cmp函数传入,具体看下面一个题目
日期排序
有一些日期,日期格式为 “MM/DD/YYYY”。
编程将其按日期大小排列。输入格式:
输入第一行一个整数 n(1≤n≤1000),表示日期的个数。
接下来 n 行按照题目描述的格式输入 n 个日期。
输出格式:
输出从早到晚排序后的日期,一个日期占一行,日期输出的格式和输入一样。
代码:
from functools import cmp_to_key
def mycmp(a,b):
if a[2]>b[2]:
return 1
elif a[2]==b[2]:
if a[0]>b[0]:
return 1
elif a[0]==b[0]:
if a[1]>b[1]:
return 1
else:
return -1
else:
return -1
else:
return -1
list=[]
n=int(input())
for i in range(n):
item=input()
a=[]
a.append(int(item[0:2]))
a.append(int(item[3:5]))
a.append(int(item[6:]))
list.append(a)
list.sort(key=cmp_to_key(mycmp))
# 也可以这么写,先按x[2]升序,然后按x[0]升序,然后按x[1]升序
#list.sort(key=lambda x:(x[2],x[0],x[1]))
for item in list:
if item[0]<10:
print(0,end="")
print("{}/".format(item[0]),end="")
if item[1]<10:
print(0,end="")
print("{}/".format(item[1]),end="")
print(item[2])
对于cmp函数的写法,这里举例一个简单的,如果传入的参数a和b,首先比较a[0]和b[0],如果a[0]>b[0],返回1,则表示以第一个元素按升序排序,如果返回-1,则是降序排序,当a[0]==b[0]时,开始比较第二个元素,如果a[1]>b[1],返回-1,则表示第一个元素相等,第二个元素按降序排序。
这个cmp函数表示,按第一个元素的升序和第二个元素的降序进行排序
def mycmp(a,b):
if a[0]>b[0]:
return 1
elif a[0]==b[0]:
if a[1]>b[1]:
return -1
else:
return 1
else:
return -1
调用sort时,将cmp传入即可,注意需要导相应的库
from functools import cmp_to_key
list.sort(key=cmp_to_key(mycmp))
例如:
from functools import cmp_to_key
def mycmp(a,b):
if a[0]>b[0]:
return 1
elif a[0]==b[0]:
if a[1]>b[1]:
return -1
else:
return 1
else:
return -1
list=[[5,0],[5,8],[3,5],[5,2],[0,3],[0,5]]
list.sort(key=cmp_to_key(mycmp))
print(list)
# 输出:[[0, 5], [0, 3], [3, 5], [5, 8], [5, 2], [5, 0]]
上边写法过于复杂,可以直接使用lambda表达式来写
#先按x[2]升序,然后按x[0]升序,然后按x[1]升序
list.sort(key=lambda x:(x[2],x[0],x[1]))