如何生成无连续重复项的随机列表?解决食物分配死循环问题
问题分析与解决方案
核心问题拆解
你的代码存在两个关键问题导致死循环和逻辑错误:
- 全局共享历史选中项:
before_picked_item是全局变量,会跨食物类别(主食/肉类/蔬菜)限制选择,比如选完主食Potato后,选肉类时会错误避开Potato,不符合「同一类别相邻天数不重复」的需求。 - 死循环触发条件:当某类别只剩一种食物且与上一次选中项重复时,
while循环会无限尝试随机选择其他选项,但无其他选项可选,陷入死循环。 - 隐性错误:未导入
random模块,直接使用rand.choice会运行报错;且直接修改原始食物计数字典,导致后续无法复用数据。
修复后的代码
import random days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'] main = {'Potato': 2, 'Rice': 2, 'Spaghetti': 1} meat = {'Chicken': 2, 'Salmon': 2, 'Beef': 1} veg = {'Corn & Broccoli': 2, 'Prawn Bit Root Salad': 1, 'Small Corn & Broccoli': 2} list_of_all_food_items = [main, meat, veg] days_to_generate_for = 5 def get_random_item(items: dict, last_item: str) -> str: available_items = list(items.keys()) # 仅当可用选项不止1个时,才排除上一次选中的项 if last_item is not None and len(available_items) > 1: candidates = [item for item in available_items if item != last_item] else: candidates = available_items # 随机选择候选项 item = random.choice(candidates) # 更新剩余计数,移除已用完的食物 items[item] -= 1 if items[item] == 0: del items[item] return item def generate_random_days() -> dict: days_generated = [] for food_type in list_of_all_food_items: # 复制原始字典,避免修改原始数据 food_copy = food_type.copy() daily_foods = [] last_selected = None for _ in range(days_to_generate_for): selected = get_random_item(food_copy, last_selected) daily_foods.append(selected) last_selected = selected days_generated.append(daily_foods) # 将天数与对应食物组合成直观字典 return dict(zip(days, zip(*days_generated))) # 生成并打印结果 weekly_plan = generate_random_days() for day, foods in weekly_plan.items(): print(f"{day}: 主食={foods[0]}, 肉类={foods[1]}, 蔬菜={foods[2]}")
关键修复点说明
- 类别独立维护历史项:每个食物类别单独维护
last_selected变量,仅限制同一类别内的相邻天数选择,不同类别之间无限制,符合需求逻辑。 - 动态候选列表:当可用选项多于1个时才排除上一次选中项;若只剩唯一选项(即使重复),直接选择该选项,彻底避免死循环。
- 保护原始数据:通过
food_type.copy()复制字典进行操作,原始食物计数字典不会被修改,可重复使用。 - 修复模块缺失:补充
import random,解决运行报错问题。
内容的提问来源于stack exchange,提问作者ThisQRequiresASpecialist
相关产品推荐
相关产品推荐

