Django模型:字段元组过滤与无冲突课程查询实现问题
嘿,这个需求我之前做课表系统的时候刚好碰到过,咱们一步步拆解来解决哈!
首先得明确冲突的核心判定规则:两个课程只要满足「在同一天上课」并且「时间区间有重叠」,就算冲突。反过来,无冲突的课程要么完全不在同一天,要么同一天但时间完全不交叉。
1. 先搞定日期匹配的逻辑
你的日期字段是"MoTuWeThFr"这种字符串,每个两位字母代表星期几(Mo=周一、Tu=周二,以此类推)。首先得把这种字符串拆成单个星期几的集合,这样才能快速判断两个课程有没有共同的上课日。
写个简单的辅助函数来拆分:
def get_weekday_set(date_str): # 把连续的日期字符串拆成单个星期几的集合,比如"MoTuWe" → {"Mo", "Tu", "We"} return set([date_str[i:i+2] for i in range(0, len(date_str), 2)])
2. 再处理时间重叠的判断
时间重叠是个经典的区间问题:只要课程A的开始时间 < 课程B的结束时间,同时课程A的结束时间 > 课程B的开始时间,就说明两个时间区间有重叠。
假设你的时间字段是datetime.time类型,或者可以转换成分钟数(比如把"09:00"转成9*60=540),写个辅助函数:
def is_time_overlap(start1, end1, start2, end2): # 支持datetime.time或整数分钟数的比较 return start1 < end2 and end1 > start2
3. 筛选无冲突课程的主逻辑
假设你有已添加课程列表enrolled_courses,现在要从所有课程all_courses里挑出无冲突的,直接循环判断就行:
def get_conflict_free_courses(all_courses, enrolled_courses): conflict_free_list = [] for course in all_courses: course_days = get_weekday_set(course.days) course_start = course.start_time course_end = course.end_time # 标记当前课程是否和任意已添加课程冲突 has_conflict = False for enrolled_course in enrolled_courses: enrolled_days = get_weekday_set(enrolled_course.days) # 先检查有没有共同的上课日 if course_days & enrolled_days: # 有共同日期,再检查时间是否重叠 if is_time_overlap(course_start, course_end, enrolled_course.start_time, enrolled_course.end_time): has_conflict = True break # 只要冲突就不用再看其他已添加课程了 if not has_conflict: conflict_free_list.append(course) return conflict_free_list
4. 可选的优化建议
如果课程数量特别多,上面的循环效率可能不够,可以试试这几个优化点:
- 按星期分组已添加课程:把已添加课程按星期几分类(比如
{"Mo": [周一的课程], "Tu": [周二的课程]}),这样筛选时只需要检查当前课程对应星期的已添加课程,不用遍历全部。 - 时间转分钟数存储:把开始/结束时间转换成整数分钟数(比如09:00→540),比较起来比时间对象更快。
- ORM层面筛选(如果用Django等框架):可以把日期不重叠的课程先通过数据库查询筛出来,剩下的再在内存里处理时间冲突,减少内存压力。比如用Django的
Q查询排除包含已添加课程星期几的课程。
另外要注意:确保日期字符串的格式统一,比如有没有大小写差异(比如"mo"和"Mo"),如果有的话,处理前先统一转成大写或小写。
内容的提问来源于stack exchange,提问作者Jason Valladares
相关产品推荐
相关产品推荐

