Python实现无重复配对且无共同角色的随机配对代码正确性验证咨询
Python实现无重复配对且无共同角色的随机配对代码正确性验证咨询
我现在需要实现一个公司内部的随机配对功能,核心要求有两个:
- 生成的配对从未在历史记录中出现过(包括反向配对,比如A-B和B-A算同一个配对,不能重复生成)
- 配对的两人不能有任何共同的角色/头衔(比如Marcus Liu和Elena Petrova都有"Stream 3"角色,就不能配对)
我已经写了一段代码来实现这个功能,逻辑是先加载CSV里的历史配对记录,随机打乱人员列表后尝试配对,跳过不符合条件的组合,最后把新生成的配对追加保存回CSV。但我不确定代码是否完全符合预期,想请大家帮忙验证逻辑,或者指出可能存在的漏洞。
我的实现代码
import random import pandas as pd # 人员姓名及对应角色数组 names_and_titles = [ ("Samantha Reyes", "Innovation", "Product Owner"), ("Ethan McAllister", "Data Scientist"), ("Priya Deshmukh", "Data Architect", "SMT"), ("Marcus Liu", "Stream 3"), ("Elena Petrova", "SMT", "Stream 3"), ] # 从CSV加载已生成的历史配对 def load_seen_pairs_from_csv(prev_pairs2): df = pd.read_csv(prev_pairs2) seen_pairs = set() for _, row in df.iterrows(): pair = (row['name1'], row['name2']) reverse_pair = (row['name2'], row['name1']) seen_pairs.add(pair) seen_pairs.add(reverse_pair) return seen_pairs # 将新配对保存到CSV def save_pairs_to_csv(prev_pairs2, pairs): df = pd.DataFrame(pairs, columns=['name1', 'name2']) df.to_csv(prev_pairs2, index=False, mode='a', header=False) # 历史配对CSV文件路径 csv_file_path = 'prev_pairs2.csv' # 初始化已出现的配对集合 seen_pairs = load_seen_pairs_from_csv(csv_file_path) # 额外需要排除的配对(当前为空) excluded_pairs = [] def create_unique_pairs_with_debugging_and_fallback(names_and_titles, seen_pairs, excluded_pairs): excluded_set = set(excluded_pairs) | set((pair[1], pair[0]) for pair in excluded_pairs) # 包含反向配对 max_retries = 10000 # 增加重试次数提高配对成功率 retries = 0 while retries < max_retries: random.shuffle(names_and_titles) pairs = [] used_names = set() # 记录本次运行中已配对的人员 skipped = [] # 记录跳过的人员用于调试 for i in range(0, len(names_and_titles) - 1, 2): person1, person2 = names_and_titles[i], names_and_titles[i + 1] # 获取两人的角色集合(处理不同长度的元组) roles1 = set(person1[1:]) if len(person1) > 1 else set() roles2 = set(person2[1:]) if len(person2) > 1 else set() pair = (person1[0], person2[0]) reverse_pair = (person2[0], person1[0]) # 调试日志:输出跳过原因 if pair in excluded_set or reverse_pair in excluded_set: print(f"因在排除列表中,跳过配对: {person1[0]} - {person2[0]}") continue if pair in seen_pairs or reverse_pair in seen_pairs: print(f"因已存在历史配对,跳过配对: {person1[0]} - {person2[0]}") continue if roles1 & roles2: # 角色有交集则跳过 print(f"因存在共同角色,跳过配对: {person1[0]} ({roles1}) - {person2[0]} ({roles2})") continue if person1[0] in used_names or person2[0] in used_names: print(f"因人员已被配对,跳过配对: {person1[0]} - {person2[0]}") continue pairs.append((person1, person2)) used_names.update([person1[0], person2[0]]) # 标记人员为已使用 # 收集未被配对的人员 skipped = [person for person in names_and_titles if person[0] not in used_names] if not skipped: # 所有人都成功配对 pairs_set = set((pair[0][0], pair[1][0]) for pair in pairs) # 再次验证配对是否都不在历史记录中(双重保险) if not any((pair in seen_pairs or (pair[1], pair[0]) in seen_pairs) for pair in pairs_set): seen_pairs.update(pairs_set) return pairs retries += 1 # 重试次数耗尽仍无法完成配对 print("无法在给定限制条件下生成有效配对。") print(f"未被配对的人员: {[person[0] for person in skipped]}") raise ValueError("无法在给定限制条件下生成有效配对。") # 生成符合要求的唯一配对 unique_pairs = create_unique_pairs_with_debugging_and_fallback(names_and_titles, seen_pairs, excluded_pairs) # 输出配对结果(仅姓名) for pair in unique_pairs: print(f"{pair[0][0]} - {pair[1][0]}") print("-----") # 输出配对总数 print(f"总配对数: {len(unique_pairs)}") # 将新配对保存到CSV save_pairs_to_csv(csv_file_path, [(pair[0][0], pair[1][0]) for pair in unique_pairs])
我的疑问与验证点
- 角色判断逻辑:我最初误写为
roles1 = set(person1[2:]),后来修正为person1[1:](因为元组第一个元素是姓名,后续所有元素都是角色),这个修正是否正确? - 奇数人数处理:当人员数量为奇数时,总会有1人无法配对,代码会一直重试直到找到全员可配对的组合吗?但如果历史配对积累到一定程度,可能确实无法生成全员配对,这种场景的报错处理是否合理?
- CSV追加逻辑:使用
mode='a'追加写入新配对,结合生成时的历史配对检查,是否能绝对避免重复写入同一配对? - 反向配对处理:代码中把A-B和B-A都加入历史配对集合,是否能完全防止反向配对被重复生成?
- 还有没有其他我没考虑到的逻辑漏洞?比如人员重复配对、角色交集判断错误等?




