107 lines
4.2 KiB
Python
107 lines
4.2 KiB
Python
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)}')
|