如何使用“Nones last”对列表进行排序

时间:2013-11-08 21:25:38

标签: python list sorting

我正在用密钥对序列列表进行排序:

groups = sorted(groups, key=lambda a: a['name'])

某些dicts的名称设置为None,而Python 2将None值放在任何其他值之前,因此它们位于排序列表的前面。一个天真的解决方案是

groups = sorted(groups, key=lambda a: a['name'] or 'zzzz')

但显然,这对任何非拉丁名称都不起作用。

对包含None值的列表进行排序以使这些值放在列表末尾有什么好的和Pythonic方式?

2 个答案:

答案 0 :(得分:14)

你可以通过在元组上键入它来实现这一点:

groups = sorted(groups, key=lambda a: (a['name'] is None, a['name']))

这是有效的,因为Python按字典顺序比较元组(在第一个元素上,然后在第二个元素上断开关系),并且因为False早于True排序。像

这样的组列表
[{'name': 0}, {'name': 1}, {'name': 2}, {'name': 3}, {'name': 4}, {'name': None}]

将成为

[(False, 0), (False, 1), (False, 2), (False, 3), (False, 4), (True, None)]

True开头的元组必然会在结尾处结束,其余的,因为第一个值绑定,将按第二个值排序。

答案 1 :(得分:2)

您可以创建自己的“无限”对象:

from functools import total_ordering

@total_ordering
class Infinity:
    def __eq__(self, other):
        return type(other) == Infinity
    def __lt__(self, other):
        return False

像这样使用它:

>>> lis = [{'name': 1}, {'name': None}, {'name': 0}, {'name': 2}]
>>> sorted(lis, key=lambda a: Infinity() if a['name'] is None else a['name'])
[{'name': 0}, {'name': 1}, {'name': 2}, {'name': None}]