【问题标题】:sort a list of objects in Python, based on an attribute (even they are NoneType) of the objects根据对象的属性(即使它们是 NoneType),对 Python 中的对象列表进行排序
【发布时间】:2016-07-04 03:53:40
【问题描述】:

我有包含发票对象的发票列表。 我想根据它们的日期订购这些对象并在下面使用。

from operator import attrgetter
invoices_list.sort(key=attrgetter('date'))

这是我得到的错误。

TypeError: can't compare FakeDatetime to NoneType

我想根据日期对对象进行升序,并且没有日期应该是第一个。然后其他人应该按升序排列。

$ invoices_list[0].date
$ FakeDatetime(2015, 7, 3, 0, 0)

【问题讨论】:

  • 给我们看看invoices_list的内容吧?
  • 您希望日期等于None 的对象出现在排序顺序的哪个位置?
  • 这意味着该列表中的元素之一具有None 日期
  • 是的,我知道没有日期。但我也想订购它们。我希望先显示无日期,然后按升序显示其他日期

标签: python list sorting object


【解决方案1】:

一个简单的密钥包装器就可以完成这项工作:

class DateKey(object):
    def __init__(self, invoice):
        self.value = invoice.date
    def __lt__(self, other):
        if not isinstance(other, (datetime.date, type(None))):
            return NotImplemented
        elif self.value is None:
            return True
        elif other.value is None:
            return False
        else:
            return self.value < other.value

然后使用它:

invoices_list.sort(key=lambda i: DateKey(i))

【讨论】:

    【解决方案2】:

    编写一个知道如何比较FakeDateTime 和None 对象的自定义比较函数,然后通过指定cmp 关键字参数告诉sort() 使用此函数。

    【讨论】:

      【解决方案3】:

      如果你有一些 None 的默认值(比如 0),你可以这样做:

      invoices_list.sort(key=lambda invoice: invoice.get('date') if (invoice != None) else 0)
      

      【讨论】:

        【解决方案4】:

        由于您没有指定FakeDatetime 的结构,我将尝试通过内置datetime 模块解决您的问题。

        基本上,即使date 是None,您也希望对列表进行排序。为此,您必须在获取None 日期时使用默认值。因此,在我的解决方案中,当我获得None 日期时,我将尽可能小的日期作为默认值。因此,所有具有None 日期的元素都将被放在排序列表的顶部。

        import datetime
        
        def get_key(d):
            return d.date if hasattr(d, 'date') and d.date is not None else datetime.date(datetime.MINYEAR, 1, 1)
        
        sorted(invoices_list, key=get_key)
        

        【讨论】:

        • invoices_list[0].date FakeDatetime(2015, 7, 3, 0, 0)
        猜你喜欢
        • 2021-06-27
        • 2022-01-05
        • 2019-02-11
        相关资源
        最近更新 更多