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

时间:2012-10-19 09:48:32

标签: python python-3.x python-2to3

我正在尝试使用

对对象列表进行排序

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

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

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

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

4 个答案:

答案 0 :(得分:23)

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

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()

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

mylist.sort(key=lambda x: Min if x is None else x)

答案 1 :(得分:20)

排序比较运算符对Python 3中的类型更为严格,如here所述:

  

排序比较运算符(&lt;,&lt; =,&gt; =,&gt;)引发TypeError   操作数没有有意义的自然顺序时的异常。

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

>>> None < None
False

>>> None < "abc"
True

>>> None < ""
True

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

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

我能想到的最快的解决方法是明确将None个实例映射到像""这样的可订购项:

my_list_sortable = [(x or "") for x in my_list]

如果您想对数据进行排序,同时保持数据完好无损,只需提供sort自定义key方法:

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

my_list.sort(key=nonesorter)

答案 2 :(得分:3)

由于None除了my_list.sort(key=lambda x: x if isinstance(x, str) else "") 之外还有其他东西不能与字符串(整数和列表,对于初学者)相比,这里是一个更稳健的解决方案:

str

这将允许字符串和从"ZZZZ"派生的任何类型作为它们自己进行比较,并将其他所有内容与空字符串进行比较。或者,如果您愿意,可以替换其他默认默认密钥,例如chr(sys.maxunicode)或{{1}}使这些元素在最后排序。

答案 3 :(得分:3)

这里提出的解决方案有效,但可以进一步缩短:

mylist.sort(key=lambda x: x or '')