基于人员可用性的每周排班表生成代码优化:解决未处理Unavailable状态问题
嘿,我来帮你把这个排班脚本给理顺!你的核心需求是处理Unavailable状态、避免覆盖已分配班次,同时严格遵守每人每周最多值2次班的规则对吧?咱们先拆解原代码的问题,再给出清晰的优化方案。
原代码的核心问题
- 完全没对
Unavailable状态做校验,存在把班次分配给明确不可值班员工的风险 - 直接修改其他员工的字典(比如
SUE[key] = "BOB")是非常混乱的写法,应该用独立变量跟踪排班和员工值班次数 - 统计员工值班次数的逻辑错误,比如
res只遍历了SUE的字典,完全没抓到真实的分配情况 - 最后补全空白班次的代码引用了循环外的
value和key,会导致逻辑完全失效
优化后的思路
我们把整个排班流程拆成清晰的三步,全程严格遵守规则:
- 优先处理"Preferred"班次:给标记了优先的员工分配对应班次,同时检查两个条件:该员工本周值班次数还没到2次,且该班次还未被分配,同时员工当天不是
Unavailable(虽然理论上优先和不可用不会共存,但做个兜底) - 实时记录值班次数:每分配一个班次就更新对应员工的计数,确保不超过每周2次的上限
- 填充空白班次:对还没分配的班次,从可用(非Unavailable)且值班次数未满2次的员工中挑选分配,彻底避免冲突
完整优化代码
# 员工每周偏好:统一放在列表里,方便遍历和维护 employees = [ {"name": "BOB", "availability": {"Monday": "Preferred", "Tuesday": "Unavailable", "Wednesday": None, "Thursday": None, "Friday": "Preferred"}}, {"name": "SUE", "availability": {"Monday": "Unavailable", "Tuesday": "Preferred", "Wednesday": None, "Thursday": None, "Friday": "Preferred"}}, {"name": "JOHN", "availability": {"Monday": "Unavailable", "Tuesday": "Unavailable", "Wednesday": "Unavailable", "Thursday": "Unavailable", "Friday": "Unavailable"}}, {"name": "BILLY", "availability": {"Monday": None, "Tuesday": None, "Wednesday": None, "Thursday": None, "Friday": None}} ] # 初始化排班表和员工值班次数统计 shift_assignment = {day: None for day in ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]} shift_count = {emp["name"]: 0 for emp in employees} # 第一步:处理所有Preferred班次 for emp in employees: emp_name = emp["name"] for day, status in emp["availability"].items(): # 多重校验:状态是Preferred、班次未分配、员工值班次数未满2次、当天不是Unavailable if status == "Preferred" and shift_assignment[day] is None and shift_count[emp_name] < 2 and emp["availability"][day] != "Unavailable": shift_assignment[day] = emp_name shift_count[emp_name] += 1 # 第二步:填充空白班次(优先选值班次数少、且当天可用的员工) for day in shift_assignment: if shift_assignment[day] is None: # 筛选符合条件的员工:当天可用+值班次数未满2次 eligible_employees = [ emp["name"] for emp in employees if emp["availability"][day] != "Unavailable" and shift_count[emp["name"]] < 2 ] # 这里默认选第一个符合条件的,你也可以改成轮询/随机等规则 if eligible_employees: selected_emp = eligible_employees[0] shift_assignment[day] = selected_emp shift_count[selected_emp] += 1 # 输出结果 print("最终排班表:") for day, emp in shift_assignment.items(): print(f"{day}: {emp}") print("\n员工值班次数统计:") for emp, count in shift_count.items(): print(f"{emp}: {count}次")
代码关键细节说明
- 统一数据结构:把所有员工信息整合到列表中,避免单独处理每个员工的冗余代码,后续加人改规则都更方便
- Unavailable严格拦截:在分配班次的所有环节,都会排除当天状态为
Unavailable的员工,绝对不会出现违规分配 - 避免覆盖已分配班次:只有当班次处于未分配状态(
shift_assignment[day] is None)时,才会执行分配操作 - 值班次数实时控制:每次分配后立即更新计数,确保每个员工的值班次数始终不超过2次
- 弹性扩展:如果以后要调整空白班次的分配规则(比如轮询、按员工意愿排序),只需要修改
eligible_employees的选择逻辑即可
内容的提问来源于stack exchange,提问作者dawsboss
相关产品推荐
相关产品推荐

