【问题标题】:Finding the earliest date in list of custom date objects在自定义日期对象列表中查找最早日期
【发布时间】:2021-12-23 07:06:54
【问题描述】:

给定一个日期对象列表,我需要找到文件中最早出现的日期

为此,我编写了以下代码:

return min(dates, key=lambda x: x.year)

每个对象都有一个年、月和日属性。 我必须使用我创建的自定义类(在帖子底部)

此代码一直有效,直到有两个日期为同一年份。如果两个日期的年份相同,则返回列表中最先出现的日期,这不是预期的。

例如这两个日期:

1988 10 10
1988 09 03

该函数应该返回 1988 09 03,但它会返回 1988 10 10,因为它首先出现。

如何在python中比较一个对象的多个值?

我也试过这个

return min(min(min(dates, key=lambda x: x.year), key=lambda x: x.month), key=lambda x: x.day)

但它似乎不起作用

我也试过了

return min(dates)

但这只是返回列表中的最后一个日期

日期文件示例:

1954 10 04
1987 12 20
1993 3 10
1996 7 29
1994 5 30
1993 6 9
1989 12 21
2001 6 30
1995 6 14
2002 2 28
1988 6 21
class Date(object):
    def __init__(self, year, month=1, day=1):
        self.year = year
        self.month = month
        self.day = day

    def __str__(self):
        return '{}/{}/{}'.format(self.year, self.month, self.day)

    def __lt__(self, other):
        return (self.year, self.month, self.day) < (other.year, other.month, other.day)

    def __gt__(self, other):
        return (self.year, self.month, self.day) > (other.year, other.month, other.day)

    def __eq__(self, other):
        return (self.year, self.month, self.day) == (other.year, other.month, other.day)

    def __le__(self, other):
        return (self.year, self.month. self.day) <= (other.year, other.month, other.day)

    def __ge__(self, other):
        return (self.year, self.month, self.day) >= (other.year, other.month, other.day)

    def __ne__(self, other):
        return (self.year, self.month, self.day) != (other.year, other.month, other.day)

解析:

def parse_dates(content):
    dates = []
    for line in content:
        line_date = line.strip().split()
        dates.append(Date(line_date[0], line_date[1], line_date[2]))

    return dates

文件被简单地打开,然后通过它返回一个日期对象列表

然后,传入这个返回最早的日期:

def find_earliest(dates):
    return min(dates)
The file where the dates are retrieved from is shown above

已解决 我没有将日期转换为 int,因此它们保留为字符串,因此程序正在比较字符串而不是实际数值。我只是将所有内容都转换为 int 然后创建了日期对象。

【问题讨论】:

    标签: python python-3.x list class object


    【解决方案1】:

    如果您没有在 Date 构造函数中强制转换为 int,则需要在解析中进行:

    def parse_dates(content):
        dates = []
        for line in content:
            line_date = line.strip().split()
            dates.append(Date(*map(int, line_date)))
    
        return dates
    

    或作为单行:

    def parse_dates(content):
        return [Date(*map(int, line.strip().split())) for line in content]
    

    如果不想定义所有的dunder比较方法,可以使用functools.total_ordering

    from functools import total_ordering
    
    @total_ordering
    class Date(object):
        def __init__(self, year, month=1, day=1):
            #cast your values to ints
            self.year  = int(year)
            self.month = int(month)
            self.day   = int(day)
    
        def __str__(self):
            # using f-string and padding
            # to get "1994/02/07" instead of "1994/2/7"
            return f'{self.year}/{self.month:02}/{self.day:02}'
    
        def __eq__(self, other):
            return self.year  == other.year
               and self.month == other.month
               and self.day   == other.day
    
        def __lt__(self, other):
            # works because `or` short-circuits on first True
            return self.year  < other.year
                or self.month < other.month
                or self.day   < other.day
    

    【讨论】:

    • return (self.year, self.month, self.day) &lt; (other.year, other.month, other.day)
    • 它使用字典顺序(proof),所以答案是肯定的。尽管您的选项不会初始化元组,但它的性能会更好。
    • 我应该说解决这个特殊问题 (使用内置min()在列表中找到最小值)你不会需要total_ordering装饰器,但绝对值得一提。
    • @OlvinR​​oght 是的 - 如果这是对对象使用的分配,可能是装饰器和使用它们是他们尚未涵盖的内容,哈哈。
    • @JoshuaVoskamp,如果您不想定义一些自定义错误消息,则根本没有理由做任何事情,因为int() 会抛出ValueError 本身。
    猜你喜欢
    • 2012-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-11
    • 2012-11-20
    • 2019-06-21
    • 2020-05-23
    相关资源
    最近更新 更多