按可以为None的属性对列表进行排序

Ale*_*Vhr 19 python python-2to3 python-3.x

我正在尝试使用排序对象列表

my_list.sort(key=operator.attrgetter(attr_name))

但如果有任何列表项attr = None而不是attr = 'whatever',

然后我得到了 TypeError: unorderable types: NoneType() < str()

在Py2中,这不是问题.我如何在Py3中处理这个?

aug*_*rar 25

对于一般解决方案,您可以定义一个比任何其他对象更少的对象:

from functools import total_ordering

@total_ordering
class MinType(object):
    def __le__(self, other):
        return True

    def __eq__(self, other):
        return (self is other)

Min = MinType()
Run Code Online (Sandbox Code Playgroud)

然后使用排序键替换列表中的Min任何None

mylist.sort(key=lambda x: Min if x is None else x)
Run Code Online (Sandbox Code Playgroud)


jsa*_*nen 22

排序比较运算符约在Python 3种严格,如描述在这里:

当操作数没有有意义的自然顺序时,排序比较运算符(<,<=,> =,>)会引发TypeError异常.

Python 2 None在任何字符串(甚至空字符串)之前排序:

>>> None < None
False

>>> None < "abc"
True

>>> None < ""
True
Run Code Online (Sandbox Code Playgroud)

在Python 3中,任何排序NoneType实例的尝试都会导致异常:

>>> None < "abc"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: NoneType() < str()
Run Code Online (Sandbox Code Playgroud)

我能想到的最快的解决方案是将None实例显式映射到可订购的东西,如"":

my_list_sortable = [(x or "") for x in my_list]
Run Code Online (Sandbox Code Playgroud)

如果要在保持数据完整性的同时对数据进行排序,只需提供sort自定义key方法:

def nonesorter(a):
    if not a:
        return ""
    return a

my_list.sort(key=nonesorter)
Run Code Online (Sandbox Code Playgroud)


fra*_*lau 6

此处提出的解决方案有效,但是可以进一步缩短:

mylist.sort(key=lambda x: x or 0)
Run Code Online (Sandbox Code Playgroud)

本质上,我们可以将None的值视为0。

例如:

>>> mylist = [3, 1, None, None, 2, 0]
>>> mylist.sort(key=lambda x: x or 0)
>>> mylist
[None, None, 0, 1, 2, 3]
Run Code Online (Sandbox Code Playgroud)


eci*_*eci 5

处理None独立于要排序的类型的通用解决方案:

my_list.sort(key=lambda x: (x is not None, x))
Run Code Online (Sandbox Code Playgroud)

None价值观放在第一位。

请注意:将值my_list.sort(key=lambda x: (x is None, x))放在最后。None