init
This commit is contained in:
106
calculate_matches.py
Normal file
106
calculate_matches.py
Normal 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)}')
|
||||
Reference in New Issue
Block a user