This commit is contained in:
2026-04-28 15:13:03 +08:00
commit 876712fe7e
6 changed files with 1015 additions and 0 deletions

106
calculate_matches.py Normal file
View File

@@ -0,0 +1,106 @@
import pandas as pd
# 读取数据
teachers_df = pd.read_excel('老师信息示例.xlsx')
students_df = pd.read_excel('学生信息示例.xlsx')
# 准备数据
teachers = []
for _, row in teachers_df.iterrows():
teacher = {'id': row['老师ID'], 'name': row['姓名']}
availability = {}
for col in teachers_df.columns:
if col not in ['老师ID', '姓名', '其他信息']:
time_slots = []
if isinstance(row[col], str):
for slot in row[col].split(';'):
slot = slot.strip()
if slot:
start, end = slot.split('-')
time_slots.append((start, end))
availability[col] = time_slots
teacher['availability'] = availability
teachers.append(teacher)
students = []
for _, row in students_df.iterrows():
student = {'id': row['学生ID'], 'name': row['姓名']}
history = []
if isinstance(row['历史匹配老师'], str):
history = [t.strip() for t in row['历史匹配老师'].split(',')]
student['history'] = history
availability = {}
for col in students_df.columns:
if col not in ['学生ID', '姓名', '历史匹配老师', '其他信息']:
time_slots = []
if isinstance(row[col], str):
for slot in row[col].split(';'):
slot = slot.strip()
if slot:
start, end = slot.split('-')
time_slots.append((start, end))
availability[col] = time_slots
student['availability'] = availability
students.append(student)
# 创建老师字典,方便查找
teachers_dict = {teacher['id']: teacher for teacher in teachers}
# 收集所有可能的匹配
possible_matches = []
for student in students:
for teacher in teachers:
if teacher['id'] in student['history']:
continue
for day, student_slots in student['availability'].items():
if day not in teacher['availability']:
continue
teacher_slots = teacher['availability'][day]
for s_slot in student_slots:
if s_slot in teacher_slots:
possible_matches.append((student['id'], student['name'], teacher['id'], teacher['name'], day, s_slot))
# 为每个学生分配一个匹配
# 使用贪心算法,优先匹配可用选项最少的学生
students_sorted = sorted(students, key=lambda s: len([m for m in possible_matches if m[0] == s['id']]))
matched_teachers = set()
matched_slots = set()
current_matches = []
for student in students_sorted:
# 找到该学生的所有可能匹配,排除已匹配的老师和时间段
available_matches = []
for match in possible_matches:
if match[0] == student['id'] and match[2] not in matched_teachers:
slot_key = (match[2], match[4], match[5])
if slot_key not in matched_slots:
available_matches.append(match)
# 选择一个匹配
if available_matches:
# 选择一个老师,该老师还有最多的可用时间段
remaining_teachers = {}
for match in available_matches:
teacher_id = match[2]
remaining_slots = 0
for day, slots in teachers_dict[teacher_id]['availability'].items():
for slot in slots:
if (teacher_id, day, slot) not in matched_slots:
remaining_slots += 1
remaining_teachers[match] = remaining_slots
# 选择剩余时间段最多的老师
best_match_for_student = max(remaining_teachers, key=remaining_teachers.get)
current_matches.append(best_match_for_student)
matched_teachers.add(best_match_for_student[2])
matched_slots.add((best_match_for_student[2], best_match_for_student[4], best_match_for_student[5]))
# 输出结果
print('最优匹配结果:')
print('-' * 80)
print(f'{"学生ID":<10} {"学生姓名":<10} {"老师ID":<10} {"老师姓名":<10} {"日期":<10} {"时间段":<15}')
print('-' * 80)
for match in current_matches:
print(f'{match[0]:<10} {match[1]:<10} {match[2]:<10} {match[3]:<10} {match[4]:<10} {match[5][0]}-{match[5][1]:<15}')
print('-' * 80)
print(f'总匹配数: {len(current_matches)}')