如何优化Python中按指定索引获取对应排列项的自定义Permutation函数
笛卡尔积索引取项函数优化方案
你当前实现的逻辑本质是从多个列表的笛卡尔积中,按指定索引直接取出对应项,无需生成全量笛卡尔积结果,下面是可行的优化方案:
优化点1:提前做边界合法性校验
先计算所有子列表长度的乘积得到总可选结果数,输入index大于等于总数时直接抛出明确的ValueError,避免后续逻辑触发无意义的索引越界异常,错误提示更友好。
优化点2:重构索引计算逻辑,去掉冗余的初始化+进位流程
原来的「先初始化索引列表再从后往前进位」的逻辑可以直接替换为权重除法逻辑,更直观简洁:
- 从第一个子列表开始,计算当前位的权重 = 后续所有子列表的长度乘积
- 当前位的索引 = 剩余索引值 // 权重
- 剩余索引值 = 剩余索引值 % 权重
- 依次遍历所有子列表即可得到所有位置的索引
优化点3:移除冗余变量,简化代码结构
原来单独存储的lengths列表、迭代计数器it都可以直接移除,减少不必要的内存占用和代码冗余。
优化点4:修改输出逻辑提升复用性
把函数直接打印结果的逻辑改为返回结果列表,需要打印时可在调用侧处理,函数可以被其他业务逻辑直接复用。
基础优化版代码
def get_cartesian_item(slots, index): # 边界校验 total = 1 for s in slots: total *= len(s) if index < 0 or index >= total: raise ValueError(f"索引超出范围,有效索引区间为0~{total-1}") remaining = index result = [] for i in range(len(slots)): # 计算当前位权重 weight = 1 for j in range(i+1, len(slots)): weight *= len(slots[j]) # 计算当前位取值 current_idx = remaining // weight result.append(slots[i][current_idx]) remaining = remaining % weight return result
高性能优化版(适合子列表数量多的场景)
如果嵌套列表层数很多,可以预计算后缀权重数组,把时间复杂度从O(n²)降到O(n):
def get_cartesian_item_high_perf(slots, index): n = len(slots) # 预计算后缀权重数组:suffix_weights[i]为第i位之后所有子列表的长度乘积 suffix_weights = [1] * n for i in range(n-2, -1, -1): suffix_weights[i] = suffix_weights[i+1] * len(slots[i+1]) # 边界校验 total = suffix_weights[0] * len(slots[0]) if index < 0 or index >= total: raise ValueError(f"索引超出范围,有效索引区间为0~{total-1}") remaining = index result = [] for i in range(n): current_idx = remaining // suffix_weights[i] result.append(slots[i][current_idx]) remaining = remaining % suffix_weights[i] return result
测试验证
和你提供的原函数输出完全一致:
l = [[0, 1, 2], [0, 1, 2], [0, 1, 2]] print(get_cartesian_item(l, 26)) # 输出:[2, 2, 2] print(get_cartesian_item(l, 17)) # 输出:[1, 2, 2] print(get_cartesian_item(l, 4)) # 输出:[0, 1, 1] get_cartesian_item(l, 27) # 抛出ValueError: 索引超出范围,有效索引区间为0~26
内容的提问来源于stack exchange,提问作者Reed Graff
相关产品推荐
相关产品推荐

