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

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

排序方法

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


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

排序有两个方法


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

排序示例

1、list.sort示例


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

2、sorted示例


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

看一个实际需求

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


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、需求一:单字段排序,钱多的在前


(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'}]
"""

(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'}]
"""

(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'}]
"""

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


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'}]
"""

(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}]
"""

(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'}]
"""

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


参考

python 列表排序方法sort、sorted技巧篇

https://www.runoob.com/python/att-list-sort.html

https://www.runoob.com/python3/python3-att-list-sort.html

相关文章
|
5天前
|
Python
探索Python中的列表推导式
【10月更文挑战第38天】本文深入探讨了Python中强大而简洁的编程工具——列表推导式。从基础使用到高级技巧,我们将一步步揭示如何利用这个特性来简化代码、提高效率。你将了解到,列表推导式不仅仅是编码的快捷方式,它还能帮助我们以更加Pythonic的方式思考问题。准备好让你的Python代码变得更加优雅和高效了吗?让我们开始吧!
|
10天前
|
搜索推荐 Python
快速排序的 Python 实践:从原理到优化,打造你的排序利器!
本文介绍了 Python 中的快速排序算法,从基本原理、实现代码到优化方法进行了详细探讨。快速排序采用分治策略,通过选择基准元素将数组分为两部分,递归排序。文章还对比了快速排序与冒泡排序的性能,展示了优化前后快速排序的差异。通过这些分析,帮助读者理解快速排序的优势及优化的重要性,从而在实际应用中选择合适的排序算法和优化策略,提升程序性能。
24 1
|
18天前
|
Python
SciPy 教程 之 SciPy 模块列表 16
SciPy教程之SciPy模块列表16 - 单位类型。常量模块包含多种单位,如公制、质量、角度、时间、长度、压强、体积、速度、温度、能量、功率和力学单位。示例代码展示了力学单位的使用,如牛顿、磅力和千克力等。
15 0
|
19天前
|
JavaScript Python
SciPy 教程 之 SciPy 模块列表 15
SciPy 教程之 SciPy 模块列表 15 - 功率单位。常量模块包含多种单位,如公制、质量、时间等。功率单位中,1 瓦特定义为 1 焦耳/秒,表示每秒转换或耗散的能量速率。示例代码展示了如何使用 `constants` 模块获取马力值(745.6998715822701)。
15 0
|
19天前
|
JavaScript Python
SciPy 教程 之 SciPy 模块列表 15
SciPy教程之SciPy模块列表15:单位类型。常量模块包含多种单位,如公制、质量、角度、时间、长度、压强、体积、速度、温度、能量、功率和力学单位。功率单位以瓦特(W)表示,1W=1J/s。示例代码展示了如何使用`constants`模块获取马力(hp)的值,结果为745.6998715822701。
16 0
|
19天前
|
C语言 Python
探索Python中的列表推导式:简洁而强大的工具
【10月更文挑战第24天】在Python编程的世界中,追求代码的简洁性和可读性是永恒的主题。列表推导式(List Comprehensions)作为Python语言的一个特色功能,提供了一种优雅且高效的方法来创建和处理列表。本文将深入探讨列表推导式的使用场景、语法结构以及如何通过它简化日常编程任务。
|
20天前
|
Python
SciPy 教程 之 SciPy 模块列表 13
SciPy 教程之 SciPy 模块列表 13 - 单位类型。常量模块包含多种单位:公制、二进制(字节)、质量、角度、时间、长度、压强、体积、速度、温度、能量、功率和力学单位。示例:`constants.zero_Celsius` 返回 273.15 开尔文,`constants.degree_Fahrenheit` 返回 0.5555555555555556。
14 0
|
1月前
|
存储 安全 Serverless
Python学习四:流程控制语句(if-else、while、for),高级数据类型(字符串、列表、元组、字典)的操作
这篇文章主要介绍了Python中的流程控制语句(包括if-else、while、for循环)和高级数据类型(字符串、列表、元组、字典)的操作。
31 0
|
1月前
|
存储 JSON 数据处理
分析、总结Python使用列表、元组、字典的场景
分析、总结Python使用列表、元组、字典的场景
|
1月前
|
存储 自然语言处理 Java
【Python】列表和元组
【Python】列表和元组
20 0