文章目录

  • 一个参数比较
  • 多个参数比较


在c/c++中,遇到结构体排序类似的问题时可以直接用struct定义一个结构体,然后重写cmp函数实现结构体排序,而在python中,没有结构体,那么如何实现结构体排序?

在python中,列表有两种排序方式,分别是sortsorted

  • 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]))