1.13 通过�个关键字排�一个字典列表¶

问题¶

你有一个字典列表,你想根��个或�几个字典字段�排�这个列表。

解决方案¶

通过使用 operator 模�的 itemgetter 函数,�以�常容易的排�这样的数�结构。 �设你从数�库中检索出�网站会员信�列表,并且以下列的数�结构返回:

rows = [
    {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
    {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
    {'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
    {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
]

根�任�的字典字段�排�输入结果行是很容易实现的,代�示例:

from operator import itemgetter
rows_by_fname = sorted(rows, key=itemgetter('fname'))
rows_by_uid = sorted(rows, key=itemgetter('uid'))
print(rows_by_fname)
print(rows_by_uid)

代�的输出如下:

[{'fname': 'Big', 'uid': 1004, 'lname': 'Jones'},
{'fname': 'Brian', 'uid': 1003, 'lname': 'Jones'},
{'fname': 'David', 'uid': 1002, 'lname': 'Beazley'},
{'fname': 'John', 'uid': 1001, 'lname': 'Cleese'}]
[{'fname': 'John', 'uid': 1001, 'lname': 'Cleese'},
{'fname': 'David', 'uid': 1002, 'lname': 'Beazley'},
{'fname': 'Brian', 'uid': 1003, 'lname': 'Jones'},
{'fname': 'Big', 'uid': 1004, 'lname': 'Jones'}]

itemgetter() 函数也支�多个 keys,比如下�的代�

rows_by_lfname = sorted(rows, key=itemgetter('lname','fname'))
print(rows_by_lfname)

会产生如下的输出:

[{'fname': 'David', 'uid': 1002, 'lname': 'Beazley'},
{'fname': 'John', 'uid': 1001, 'lname': 'Cleese'},
{'fname': 'Big', 'uid': 1004, 'lname': 'Jones'},
{'fname': 'Brian', 'uid': 1003, 'lname': 'Jones'}]

讨论¶

在上�例�中, rows 被传递给接�一个关键字�数的 sorted() 内置函数。 这个�数是 callable 类型,并且从 rows 中接�一个�一元素,然�返回被用�排�的值。 itemgetter() 函数就是负责创建这个 callable 对象的。

operator.itemgetter() 函数有一个被 rows 中的记录用�查找值的索引�数。�以是一个字典键�称, 一个整形值或者任何能够传入一个对象的 __getitem__() 方法的值。 如果你传入多个索引�数给 itemgetter() ,它生�的 callable 对象会返回一个包�所有元素值的元组, 并且 sorted() 函数会根�这个元组中元素顺�去排�。 但你想��时在几个字段上�进行排�(比如通过姓和��排�,也就是例�中的那样)的时候这�方法是很有用的。

itemgetter() 有时候也�以用 lambda 表达�代替,比如:

rows_by_fname = sorted(rows, key=lambda r: r['fname'])
rows_by_lfname = sorted(rows, key=lambda r: (r['lname'],r['fname']))

这�方案也�错。但是,使用 itemgetter() 方�会�行的�微快点。因此,如果你对性能�求比较高的�就使用 itemgetter() 方�。

最�,��忘了这节中展示的技术也�样适用于 min() 和 max() 等函数。比如:

>>> min(rows, key=itemgetter('uid'))
{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}
>>> max(rows, key=itemgetter('uid'))
{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
>>>