Python编程:列表List.sort和sorted方法排序

举报
彭世瑜 发表于 2021/08/14 00:04:24 2021/08/14
【摘要】 排序方法 2.x的代码移植到3.x时,需要将cmp函数转化为key函数 # Python2 list.sort(cmp=None, key=None, reverse=False) # Python3 list.sort(key=None, reverse=False) 12345 排序有两个方法 list.sort() # list本身将被修改, 返回N...

排序方法

2.x的代码移植到3.x时,需要将cmp函数转化为key函数

# Python2
list.sort(cmp=None, key=None, reverse=False)

# Python3
list.sort(key=None, reverse=False)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

排序有两个方法

list.sort()   # list本身将被修改, 返回None
sorted() # 不修改原来的list, 返回一个新的list

  
 
  • 1
  • 2

排序示例

1、list.sort示例

lst = [3, 2, 1]
print(lst)  # [3, 2, 1]

ret = lst.sort()
print(ret)  # None
print(lst)  # [1, 2, 3]

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2、sorted示例

lst = [3, 2, 1]
print(lst)  # [3, 2, 1]

ret = sorted(lst)
print(ret)  # [1, 2, 3]
print(lst)  # [3, 2, 1]


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

看一个实际需求

有一个人员列表,需要按给定需求排序

from pprint import pprint

# name:姓名
# money:钱
# age:年龄
lst = [ { 'name': 'Tom', 'age': 20, 'money': 2000 }, { 'name': 'Jack', 'age': 25, 'money': 2000 }, { 'name': 'Alice', 'age': 25, 'money': 3000 }, { 'name': 'Steve', 'age': 25, 'money': 3000 }
]

# 未排序前
pprint(lst)
"""
[{'age': 20, 'money': 2000, 'name': 'Tom'},
 {'age': 25, 'money': 2000, 'name': 'Jack'},
 {'age': 25, 'money': 3000, 'name': 'Alice'},
 {'age': 25, 'money': 3000, 'name': 'Steve'}]
"""

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

1、需求一:单字段排序,钱多的在前

(1)使用lambda 表达式

# 默认从小到大,reverse=True可以逆序排列
lst.sort(key=lambda item: item['money'], reverse=True)
pprint(lst)
"""
[{'age': 25, 'money': 3000, 'name': 'Alice'},
 {'age': 25, 'money': 3000, 'name': 'Steve'},
 {'age': 20, 'money': 2000, 'name': 'Tom'},
 {'age': 25, 'money': 2000, 'name': 'Jack'}]
"""

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

(2)使用operator.itemgetter 替换 lambda 表达式

from operator import itemgetter

lst.sort(key=itemgetter('money'), reverse=True)
pprint(lst)

"""
[{'age': 25, 'money': 3000, 'name': 'Alice'},
 {'age': 25, 'money': 3000, 'name': 'Steve'},
 {'age': 20, 'money': 2000, 'name': 'Tom'},
 {'age': 25, 'money': 2000, 'name': 'Jack'}]
"""

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

(3)使用sorted

from operator import itemgetter

lst2 = sorted(lst, key=itemgetter('money'), reverse=True)
pprint(lst2)

"""
[{'age': 25, 'money': 3000, 'name': 'Alice'},
 {'age': 25, 'money': 3000, 'name': 'Steve'},
 {'age': 20, 'money': 2000, 'name': 'Tom'},
 {'age': 25, 'money': 2000, 'name': 'Jack'}]
"""

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

以上三种方式排序结果都一样

2、需求二:多字段排序

需要满足3个排序要求

  • 钱money 多的在前面
  • 如果钱money 一样多,年龄age 大的在前
  • 如果钱money 和年龄age 都一样,按照名字首字母顺序排序Z-A排序

如果有一个排序函数就很容易解决

(1) 方式一: 自定义一个排序函数

from functools import cmp_to_key

# 自定义一个排序函数
def foo(a, b): if a['money'] > b['money']: return 1 elif a['money'] < b['money']: return -1 else: if a['age'] > b['age']: return 1 elif a['age'] < b['age']: return -1 else: return ord(a['name'][0]) - ord(b['name'][0])

# Python3中需要用到cmp_to_key 函数
lst.sort(key=cmp_to_key(foo), reverse=True)

pprint(lst)
"""
[{'age': 25, 'money': 3000, 'name': 'Steve'},
 {'age': 25, 'money': 3000, 'name': 'Alice'},
 {'age': 25, 'money': 2000, 'name': 'Jack'},
 {'age': 20, 'money': 2000, 'name': 'Tom'}]
"""

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

(2)方式二:自定义一个class类,在类中重写排序方法


from functools import total_ordering


# 通过__eq__ 和其他(__ne__, __lt__, __gt__)任意一个方法就可以推导出来其他方法
@total_ordering
class Person(object): def __init__(self, name, age, money): self.name = name self.age = age self.money = money def __eq__(self, other): return self.money == other.money and \ self.age == other.age and \ ord(self.name[0]) - ord(other.name[0]) def __lt__(self, other): return self.money < other.money or \ self.age < other.age or \ ord(self.name[0]) - ord(other.name[0]) def __str__(self): return f"{{age: {self.age}, money: {self.money}, name: {self.name}}}" __repr__ = __str__


persons = [Person(**item) for item in lst]
new_persons = sorted(persons, reverse=True)
pprint(new_persons)
"""
[{age: 25, money: 3000, name: Steve},
 {age: 25, money: 3000, name: Alice},
 {age: 25, money: 2000, name: Jack},
 {age: 20, money: 2000, name: Tom}]
"""

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

(3)方式三:使用多个key进行排序

from operator import itemgetter

lst.sort(key=itemgetter('money', 'age', 'name'), reverse=True)

pprint(lst)
"""
[{'age': 25, 'money': 3000, 'name': 'Steve'},
 {'age': 25, 'money': 3000, 'name': 'Alice'},
 {'age': 25, 'money': 2000, 'name': 'Jack'},
 {'age': 20, 'money': 2000, 'name': 'Tom'}]
"""

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

以上3种方式实现了多个字段排序

参考
python 列表排序方法sort、sorted技巧篇
https://www.runoob.com/python/att-list-sort.html
https://www.runoob.com/python3/python3-att-list-sort.html

文章来源: pengshiyu.blog.csdn.net,作者:彭世瑜,版权归原作者所有,如需转载,请联系作者。

原文链接:pengshiyu.blog.csdn.net/article/details/112610728

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。