Python 按照某个或某几个字段来排序字典列表
目录
1. 前言
说到排序我们能想到的就是用sorted() 函数,并且可以通过key关键字参数来自定义排序的规则,假设下面是你从数据库里查询出来的网站会员信息列表:
rows = [ {‘name‘: ‘Jack‘, ‘uid‘: 1003, ‘level‘: 5}, {‘name‘: ‘Gigi‘, ‘uid‘: 1001, ‘level‘: 2}, {‘name‘: ‘Koko‘, ‘uid‘: 1005, ‘level‘: 3}, {‘name‘: ‘Eric‘, ‘uid‘: 1004, ‘level‘: 2}, {‘name‘: ‘Aven‘, ‘uid‘: 1002, ‘level‘: 6} ]
下面会演示两种方式来实现排序,lambda和itemgetter(),但是事先说明,使用itemgetter()方式运行会稍微快点,所以如果对性能要求较高的话就是用itemgetter()方式。
2. lambda表达式
sorted()函数可以结合 lambda 表达式实现对指定字典列表字段的排序:
# 根据name排序 rows_by_name = sorted(rows, key=lambda r: r[‘name‘]) # 根据uid排序 rows_by_uid = sorted(rows, key=lambda r: r[‘uid‘]) print(rows_by_name) print(rows_by_uid)
执行结果:
[{‘name‘: ‘Aven‘, ‘uid‘: 1002, ‘level‘: 6}, {‘name‘: ‘Eric‘, ‘uid‘: 1004, ‘level‘: 2}, {‘name‘: ‘Gigi‘, ‘uid‘: 1001, ‘level‘: 2}, {‘name‘: ‘Jack‘, ‘uid‘: 1003, ‘level‘: 5}, {‘name‘: ‘Koko‘, ‘uid‘: 1005, ‘level‘: 3}] [{‘name‘: ‘Gigi‘, ‘uid‘: 1001, ‘level‘: 2}, {‘name‘: ‘Aven‘, ‘uid‘: 1002, ‘level‘: 6}, {‘name‘: ‘Jack‘, ‘uid‘: 1003, ‘level‘: 5}, {‘name‘: ‘Eric‘, ‘uid‘: 1004, ‘level‘: 2}, {‘name‘: ‘Koko‘, ‘uid‘: 1005, ‘level‘: 3}]
3. itemgetter函数
使用 operator 模块的 itemgetter 函数,我们的sorted()函数可以结合它很容易的实现对字典列表字段的排序,至少比lambda简单很多。
from operator import itemgetter rows_by_name = sorted(rows, key=itemgetter(‘name‘)) rows_by_uid = sorted(rows, key=itemgetter(‘uid‘)) print(rows_by_name) print(rows_by_uid)
执行结果:
[{‘name‘: ‘Aven‘, ‘uid‘: 1002, ‘level‘: 6}, {‘name‘: ‘Eric‘, ‘uid‘: 1004, ‘level‘: 2}, {‘name‘: ‘Gigi‘, ‘uid‘: 1001, ‘level‘: 2}, {‘name‘: ‘Jack‘, ‘uid‘: 1003, ‘level‘: 5}, {‘name‘: ‘Koko‘, ‘uid‘: 1005, ‘level‘: 3}] [{‘name‘: ‘Gigi‘, ‘uid‘: 1001, ‘level‘: 2}, {‘name‘: ‘Aven‘, ‘uid‘: 1002, ‘level‘: 6}, {‘name‘: ‘Jack‘, ‘uid‘: 1003, ‘level‘: 5}, {‘name‘: ‘Eric‘, ‘uid‘: 1004, ‘level‘: 2}, {‘name‘: ‘Koko‘, ‘uid‘: 1005, ‘level‘: 3}]
itemgetter() 函数也支持多个keys,比如下面代码:
rows_by_lname = sorted(rows, key=itemgetter(‘name‘,‘level‘)) print(rows_by_uname)
执行结果:
[{‘name‘: ‘Aven‘, ‘uid‘: 1002, ‘level‘: 6}, {‘name‘: ‘Eric‘, ‘uid‘: 1004, ‘level‘: 2}, {‘name‘: ‘Gigi‘, ‘uid‘: 1001, ‘level‘: 2}, {‘name‘: ‘Jack‘, ‘uid‘: 1003, ‘level‘: 5}, {‘name‘: ‘Koko‘, ‘uid‘: 1005, ‘level‘: 3}]
rows 会被传递给只接受一个关键字参数(key=xx)的sorted()内置函数,这个参数是callable类型,并且会从rows中接受一个单一元素,然后返回被用来排序的值,itemgetter()函数就是专门负责创建这个callable对象。
4. 性能测试
我刚在上面提到了itemgetter()性能更好,那有同学会问?你怎么知道的,我们来看下面的性能测试就知道结果了:
>>> import dis >>> rows = [ ... {‘name‘: ‘Jack‘, ‘uid‘: 1003, ‘level‘: 5}, ... {‘name‘: ‘Gigi‘, ‘uid‘: 1001, ‘level‘: 2}, ... {‘name‘: ‘Koko‘, ‘uid‘: 1005, ‘level‘: 3}, ... {‘name‘: ‘Eric‘, ‘uid‘: 1004, ‘level‘: 2}, ... {‘name‘: ‘Aven‘, ‘uid‘: 1002, ‘level‘: 6} ... ] # 测试lambda性能 >>> x = lambda: sorted(rows, key=lambda r: r[‘name‘]) >>> dis.dis(x) 1 0 LOAD_GLOBAL 0 (sorted) 2 LOAD_GLOBAL 1 (rows) 4 LOAD_CONST 1 (<code object <lambda> at 0x1047cb920, file "<stdin>", line 1>) 6 LOAD_CONST 2 (‘<lambda>.<locals>.<lambda>‘) 8 MAKE_FUNCTION 0 10 LOAD_CONST 3 ((‘key‘,)) 12 CALL_FUNCTION_KW 2 14 RETURN_VALUE Disassembly of <code object <lambda> at 0x1047cb920, file "<stdin>", line 1>: 1 0 LOAD_FAST 0 (r) 2 LOAD_CONST 1 (‘name‘) 4 BINARY_SUBSCR 6 RETURN_VALUE # 测试itemgetter性能 >>> from operator import itemgetter >>> y = lambda: sorted(rows, key=itemgetter(‘name‘)) >>> dis.dis(y) 1 0 LOAD_GLOBAL 0 (sorted) 2 LOAD_GLOBAL 1 (rows) 4 LOAD_GLOBAL 2 (itemgetter) 6 LOAD_CONST 1 (‘name‘) 8 CALL_FUNCTION 1 10 LOAD_CONST 2 ((‘key‘,)) 12 CALL_FUNCTION_KW 2 14 RETURN_VALUE
可以很明显的看到 lambda 执行的步骤比 itemgetter 多了很多,所以 itemgetter 性能胜出。
相关推荐
夜斗不是神 2020-11-17
huavhuahua 2020-11-20
Yasin 2020-11-16
xiaoseyihe 2020-11-16
千锋 2020-11-15
diyanpython 2020-11-12
chunjiekid 2020-11-10
wordmhg 2020-11-06
世事一场大梦 2020-11-17
xiaoseyihe 2020-11-16
Morelia 2020-11-03
CloudXli 2020-11-03
文山羊 2020-10-31
comtop0 2020-10-31
pythonxuexi 2020-10-30
三石 2020-10-29
chaochao 2020-10-27
PythonMaker 2020-10-27