Python竞价逻辑模拟报错:索引越界问题求解(If/While循环)
竞价匹配逻辑修复方案
问题根源
你的代码触发single positional indexer is out-of-bounds的原因很明确:
- 处理单个需求时,找不到符合
demand_price > supply_price的供应时,s_row会一直递增直到超出DataFrame的索引范围 - 原逻辑只单向往下遍历供应,完全没考虑前面行还剩有可匹配的剩余供应量(比如你说的索引3的19单位剩余)
修复思路
核心是给s_row加重置机制,同时优化遍历逻辑:
- 每次处理新需求时,从上次暂停的
s_row位置开始遍历 - 若遍历到供应列表末尾仍无匹配,重置
s_row为0,再从头检查一遍剩余供应 - 加索引边界判断,防止越界
- 只有当当前供应的剩余量为0时,才移动
s_row
修复后代码示例
假设你的原始DataFrame定义是类似这样的:
import pandas as pd # 示例需求表:已按竞价优先级排序(排名越低越靠前) demand = pd.DataFrame({ 'demand_id': [1,2,3,10], 'demand_price': [100, 90, 80, 95], 'quantity': [5, 10, 15, 20] }) # 示例供应表:已按竞价优先级排序 supply = pd.DataFrame({ 'supply_id': [1,2,3,4], 'supply_price': [85, 92, 70, 93], 'quantity': [10, 5, 20, 15] })
修改后的匹配逻辑代码:
# 初始化索引 d_row = 0 s_row = 0 total_supply_rows = len(supply) matches = [] while d_row < len(demand): current_demand = demand.iloc[d_row] # 若当前需求已满足,处理下一个需求 if current_demand['quantity'] <= 0: d_row += 1 continue matched = False start_row = s_row # 最多遍历两轮:一轮从当前位置到末尾,一轮从头开始到当前位置 for _ in range(2): while s_row < total_supply_rows: current_supply = supply.iloc[s_row] # 检查供应剩余量和价格条件 if current_supply['quantity'] > 0 and current_demand['demand_price'] > current_supply['supply_price']: # 计算可交易的数量:取需求剩余和供应剩余的最小值 trade_qty = min(current_demand['quantity'], current_supply['quantity']) # 记录匹配 matches.append({ 'demand_id': current_demand['demand_id'], 'supply_id': current_supply['supply_id'], 'trade_qty': trade_qty, 'demand_price': current_demand['demand_price'], 'supply_price': current_supply['supply_price'] }) # 更新剩余量 demand.loc[d_row, 'quantity'] -= trade_qty supply.loc[s_row, 'quantity'] -= trade_qty matched = True # 若供应还剩,不移动s_row,继续用当前供应匹配剩余需求 if supply.loc[s_row, 'quantity'] > 0: break # 供应用完,移动到下一个 else: s_row += 1 break else: # 当前供应不满足,移动到下一个 s_row += 1 # 第一轮遍历完没找到,重置s_row到0,再找一次 if not matched: s_row = 0 else: break # 两轮遍历都没找到匹配,处理下一个需求 if not matched: d_row += 1 s_row = 0 # 输出匹配结果 print(pd.DataFrame(matches))
关键改动说明
- 双轮遍历机制:先从上次停止的位置找供应,找不到就重置到0再找一遍,确保不会漏掉前面的剩余供应
- 供应剩余量判断:只有当当前供应的剩余量为0时,才移动
s_row,否则继续用该供应匹配当前需求的剩余量 - 边界防护:所有
s_row的操作都有s_row < total_supply_rows的判断,完全避免索引越界 - 需求处理逻辑:当前需求剩余量为0时,才切换到下一个需求,同时保留当前
s_row位置(因为可能还有剩余供应能匹配下一个需求)
验证你的场景
针对你提到的索引3剩余19单位供应匹配索引10需求的场景:
- 处理索引10的需求时,若第一轮从当前
s_row位置没找到,会重置到0,遍历到索引3的供应,发现价格满足且有剩余量,就会完成匹配
内容的提问来源于stack exchange,提问作者Lina Antelmann
相关产品推荐
相关产品推荐

