对包含具有日期时间属性的对象的列表进行排序

Sort a list containing objects that have datetime attributes

我有 excel 个包含学生考试成绩数据的文件,他们最多可以参加 3 次考试,但我需要我的程序识别他们参加考试的顺序以及 excel文件顺序不对。我有一个 Student class 包含代表所有学生尝试的对象列表和一个 Attempt class,其中包括分数和 date/time 测试被拍了。

import datetime as dt

class Student:
    def __init__(self, last_name, first_name ):
        self.first_name = first_name
        self.last_name = last_name

        # will hold Attempt objects that consist of score and date/time test taken
        self.attempts = []

    # I imagine I need something like this
    def order_attempts(self):
        for attempt in self.attempts:
            # compare attempt.date_and_time_of_attempt to next attempt and switch if needed/create a new Student.ordered_attempts attribute?

class Attempt:
    def __init__(self, score_as_fraction, datetime_obj):
        self.score_as_fraction = score_as_fraction
        self.date_and_time_of_attempt = datetime_obj

在我的 main.py 中,跳过 excel 中的所有数据抓取和拆分,我遍历每一行并构建这些对象:

import datetime as dt
datetime_obj = dt.datetime(int(year), int(month), int(day), int(hour), int(minute))
attempt_obj = Attempt(score_as_fraction, datetime_obj)
student_obj.attempts.append(attempt_obj)

所以说在阅读一个 excel 文件后,一名学生参加了 3 次测试,因此存在一个假想的 student_obj.attempts = [<attempt.Attempt object at 0x105294da0>, <attempt.Attempt object at 0x102431c50>,<attempt.Attempt object at 0x105294f28>] 但该列表是按 excel 文件的顺序排列的,而不是尝试的时间。有什么方法可以重新排序此 attempts 列表从第一次尝试到最后一次尝试的顺序吗?我会展示我尝试过的东西,但老实说我不确定要尝试什么。我想我包含了所有必要的信息,但如果您需要更多信息,请告诉我。感谢您的帮助。

使用您发布的代码,并提到您将传递一个 excel 文件,仅通过您发布的代码无法做到这一点。您必须实际阅读 excel 文件并捕获那些 datetime obj 值。但是,如果您从发布的内容中获取实际的日期时间对象,您可以简单地使用 list.sort() 对对象列表进行排序

import datetime

yesterday = datetime.date.today() - datetime.timedelta(days=1)
today = datetime.date.today()
tomorrow = datetime.date.today() + datetime.timedelta(days=1)

date_list =[today, tomorrow, yesterday]
print(date_list)

date_list.sort()
print(date_list)

我建议像我添加的那样为 Attempt 提供一个表示。 您可以使用键对任何类型的列表进行排序。为了获得对尝试进行排序的“键”,我想告诉 sorted 方法尝试由其日期时间表示。因此,使用 lambda,我们可以实现这一点。谷歌搜索这些条款会得到你想要的。这是示例代码:

from datetime import date,datetime,timedelta

class Student:
    def __init__(self, last_name, first_name ):
        self.first_name = first_name
        self.last_name = last_name

        # will hold Attempt objects that consist of score and date/time test taken
        self.attempts = []

    # I imagine I need something like this
    def order_attempts(self):
        self.attempts = sorted(self.attempts,key= lambda attempt:attempt.date_and_time_of_attempt)

class Attempt:
    def __init__(self, score_as_fraction, datetime_obj):
        self.score_as_fraction = score_as_fraction
        self.date_and_time_of_attempt = datetime_obj
    def __repr__(self):
        return str(self.date_and_time_of_attempt)+': '+str(self.score_as_fraction)

student = Student('Doe','John')
student.attempts=[Attempt(0.8,date.today()), Attempt(0.7,date.today() + timedelta(days=1)), Attempt(0.6,date.today() - timedelta(days=1))]
print(student.attempts)
student.order_attempts()
print(student.attempts)

给予:

[2021-03-05: 0.8, 2021-03-06: 0.7, 2021-03-04: 0.6]
[2021-03-04: 0.6, 2021-03-05: 0.8, 2021-03-06: 0.7]

您可以简单地使用尝试对象的 date_and_time_of_attempt 属性作为排序键

self.attempts.sort(key = lambda attempt: attempt.date_and_time_of_attempt)

我认为真正的问题是如何对 Attempt 的实例进行排序。您可以通过添加方法 __lt__ 使 Class 尝试可排序来实现此目的,请参见下面的示例。

from datetime import datetime

class Student:

    def __init__(self, name, attempts):
        self.name = name
        self.attempts = attempts

    def order_attempts(self, reverse=False):
        self.attemtps = attempts.sort(reverse=reverse)

class Attempt:

    def __init__(self, topic, attempt_date, score):
        self.score = score
        self.attempt_date = attempt_date
        self.topic = topic

    def __lt__(self, other):
        return self.attempt_date < other.attempt_date

    def __repr__(self):
        return f'{self.attempt_date.date()}: {self.score}'

attempts = []
attempts.append(Attempt('Math', datetime(2021, 2, 3), 4))
attempts.append(Attempt('Math', datetime(2021, 2, 5), 5))
attempts.append(Attempt('Math', datetime(2021, 2, 7), 8))
stud2 = Student('Mike Owen', attempts)

stud2.order_attempts()
print(stud2.attempts)
stud2.order_attempts(reverse=True)
print(stud2.attempts)
[2021-02-03: 4, 2021-02-05: 5, 2021-02-07: 8]
[2021-02-07: 8, 2021-02-05: 5, 2021-02-03: 4]