基于Python字典(列表)Lambda函数的排序问题

    相信很多学Python的小伙伴都十分熟悉Python中的字典排序类问题,这里我就不展开说了,简单介绍一下该排序问题的要求及做法并且附上代码。

    前提摘要:sort或者sorted函数的参数reverse  =  False → 升序(默认)  /  True → 降序

    首先是字典排序类问题,举个简单的例子。例如,一个字典里的所有键是某个班同学的名字,所有值是对应同学的学积分成绩,现在需要大家输出前十名同学的名字和成绩。绝大多数同学会想到利用list(d.items())来构建一个列表对列表进行排序,接着再遍历列表,输出相应的信息。下面附上用二维列表解决排序问题的代码(这里简略用学生编号代替学生成绩):

import random
s=[]
for i in range(30):
    a = []
    a.append(i+1)
    score=random.randint(10,100)
    a.append(score)
    s.extend([a])
list = sorted(s,key = lambda x:x[1],reverse = True)  #降序排序

for i in range(10):      #输出前十位同学的成绩
    print("编号为{:02}的同学成绩是:{:2}分".format(list[i][0],list[i][1]))

    我们输出前十名同学的成绩,结果如下:

    这个问题比较简单,相信大家看代码就能看懂,下面有一个一开始另我很疑惑的问题,也是一类字典排序问题,但是要求是,首先按照字典的值进行降序排序(reverse=True),如果字典值相同的话,再按照字典的键进行升序排序(默认reverse=False),该问题也可以推广到二维列表的排序问题,为了简化理解,我就先把字典的值(或者二维列表(两列))的第一个元素换成字母,也就是,先按照字典的值也就是数字大小进行降序排列,如果两个数字相等,再按照字典的键也就是字母大小升序排序(Unicode编码)。两种思路及配套代码如下:

    首先我们创建了一个字典:

第一种思路如下:  

    我们进行键值对的封装第一次排序

l=list(d.items())    #将d的键值对封装成列表放入列表l中

l.sort(reverse=False,key=lambda x:ord(x[0]))
 
#依据l子列表中的第0个元素(字母)进行升序排序

     我们第一次排序是对字母的升序排序,结果如下:

    现在字母已经按照要求的升序排列好,现在我们需要做的是第二次排序,也就是对数字的降序排序,由于我们的优先级是:先数字后字母,也就是在数字相同的情况下才对字母进行升序排序。所以我们第二次排序对数字进行降序时不用管前面我们排好的字母顺序(也就是考虑优先级),而是在数字相同时(无法对数字进行大小排序时),此时sort函数不做数字上的大小排序,而是按照之前的遍历顺序依次排序,这时我们发现之前对字母的升序排序派上了用场,这时的遍历顺序就是在数字相同下的字母升序,符合题目要求,代码如下:

l.sort(reverse=True ,key=lambda x:x[1])  #依据l子列表中的第1个元素(数字)进行降序排序

for i in range (5):
    print(l[i][0],l[i][1],sep=' ')       #将排序结果进行打印

    最终结果如下:

第二种思路如下: 

    除了上述这种方法,我们还可以用sort函数中key参数的一个特殊传参方式来解决这个问题,原理是:sorted或者sort函数可以根据多个key值进行数据的排序,按照key值传入的顺序依次,当前面元素相同时,根据后面的key值继续排序。

    原理代码如下:

sorted(ls, key=lambda x:(x[0], x[1]))) #根据元组第0个值升序排序,若第0个值相等则根据第1个值升序排序
sorted(ls, key=lambda x:(x[0], -x[1])))#根据元组第0个值升序排序,若第0个值相等则根据第1个值降序排序

    或者用自定义函数解决:

def cmp1(x):
    return x[0], x[1]
def cmp2(x):
    return x[0], -x[1]
sorted(ls, key=cmp1))  #根据元组第0个值升序排序,若第0个值相等则根据第1个值升序排序
sorted(ls, key=cmp2))  #根据元组第0个值升序排序,若第0个值相等则根据第1个值降序排序

    实现上述题目要求代码如下:

ls = list(d.items())

ls.sort(key = lambda x:(x[1],-ord(x[0])),reverse=True) #按照第1个值降序排排序,若第1个值相同则按照第0个值升序排序

for k in ls:
        print(k[0],k[1])

    又或者(默认升序):

ls.sort(key = lambda x:(-x[1],ord(x[0]))) #按照第1个值降序排排序,若第1个值相同则按照第0个值升序排序

    最终结果均为:

    值得注意的是第一种方法是先对字母进行升序排序,再对数字进行降序排序。而第二种方法是直接依据题目要求,先对数字进行降序排序,在数字相同时再对字母进行升序排序。读者一定要严格区分二者的不同点,同时也要尽可能理解该类字典排序问题的算法思维。

    如果该篇文章对你有帮助,请记得 点赞+收藏+关注 哦 ~

  • 13
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王业强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值