如何更优雅地根据globalDepots拆分route路径列表?
更简洁优雅的Python路线拆分实现方案
需求说明
我需要将以下route列表:
route = [51, 5, 33, 39, 34, 32, 64, 53, 62, 66, 58, 59, 54, 38, 9, 21, 29, 2, 61, 11, 50, 16, 20, 28, 31, 8, 26, 43, 7, 1, 27, 60, 55, 52, 10, 30, 49, 46, 12, 15, 44, 45, 37, 56, 65, 63, 42, 19, 40, 41, 13, 25, 14, 18, 57, 48, 23, 24, 6, 3, 36, 35, 22, 17, 4, 47]
按照globalDepots列表(包含50到65的整数):
globalDepots = [i for i in range(50, 66)]
的元素位置拆分成多个miniRoute子列表,预期输出结果如下:
Total number of valid miniRoutes is 16 All mini routes: #1 [51, 5, 33, 39, 34, 32, 64] #2 [64, 53] #3 [53, 62] #4 [62, 66, 58] #5 [58, 59] #6 [59, 54] #7 [54, 38, 9, 21, 29, 2, 61] #8 [61, 11, 50] #9 [50, 16, 20, 28, 31, 8, 26, 43, 7, 1, 27, 60] #10 [60, 55] #11 [55, 52] #12 [52, 10, 30, 49, 46, 12, 15, 44, 45, 37, 56] #13 [56, 65] #14 [65, 63] #15 [63, 42, 19, 40, 41, 13, 25, 14, 18, 57] #16 [57, 48, 23, 24, 6, 3, 36, 35, 22, 17, 4, 47, 50]
现有脚本可实现该功能,但希望获得更简洁优雅的实现方式,当前代码如下:
当前实现代码
import random def countMiniRoutes(route): depotIndexes = [] for depot in globalDepots: index = route.index(depot) depotIndexes.append(index) miniRoutesList = [] sortedDepotIndexes = sorted(depotIndexes) start = sortedDepotIndexes[0] if route[-1] not in globalDepots: route.append(globalDepots[0]) for i, depotIndex in enumerate(sortedDepotIndexes): try: stop = sortedDepotIndexes[i+1]+1 except IndexError: stop = len(route) miniRoute = route[start:stop] try: dist = random.random() miniRoutesList.append(miniRoute) except ZeroDivisionError: # if dist == 0, then do not add it to miniRoutesList continue try: start = sortedDepotIndexes[i+1] except IndexError: start = sortedDepotIndexes[i] print(f"Total number of valid miniRoutes is {len(miniRoutesList)}") print("All mini routes: ") for i, route in enumerate(miniRoutesList): print(f"#{i+1} \t {route}") if __name__ == "__main__": globalDepots = [i for i in range(50, 66)] route = [51, 5, 33, 39, 34, 32, 64, 53, 62, 66, 58, 59, 54, 38, 9, 21, 29, 2, 61, 11, 50, 16, 20, 28, 31, 8, 26, 43, 7, 1, 27, 60, 55, 52, 10, 30, 49, 46, 12, 15, 44, 45, 37, 56, 65, 63, 42, 19, 40, 41, 13, 25, 14, 18, 57, 48, 23, 24, 6, 3, 36, 35, 22, 17, 4, 47] countMiniRoutes(route)
优化后的实现代码
import random def split_route(route, depots): # 转换为集合提升成员判断效率 depot_set = set(depots) # 复制原路线避免修改输入列表 working_route = route.copy() # 如果路线末尾不是 depot,添加第一个 depot 作为终点 if working_route[-1] not in depot_set: working_route.append(depots[0]) # 收集所有 depot 在路线中的索引并排序 depot_indices = sorted(idx for idx, val in enumerate(working_route) if val in depot_set) mini_routes = [] # 遍历连续的索引对生成子路线 for start_idx, end_idx in zip(depot_indices[:-1], depot_indices[1:]): mini_route = working_route[start_idx:end_idx + 1] # 原代码中 random.random() 不会触发 ZeroDivisionError,直接判断即可 if random.random() != 0: mini_routes.append(mini_route) # 处理最后一段路线 last_start = depot_indices[-1] mini_routes.append(working_route[last_start:]) # 输出结果 print(f"Total number of valid miniRoutes is {len(mini_routes)}") print("All mini routes: ") for i, mr in enumerate(mini_routes, 1): print(f"#{i}\t{mr}") if __name__ == "__main__": global_depots = list(range(50, 66)) route = [51, 5, 33, 39, 34, 32, 64, 53, 62, 66, 58, 59, 54, 38, 9, 21, 29, 2, 61, 11, 50, 16, 20, 28, 31, 8, 26, 43, 7, 1, 27, 60, 55, 52, 10, 30, 49, 46, 12, 15, 44, 45, 37, 56, 65, 63, 42, 19, 40, 41, 13, 25, 14, 18, 57, 48, 23, 24, 6, 3, 36, 35, 22, 17, 4, 47] split_route(route, global_depots)
优化说明
- 避免修改原输入:使用
route.copy()复制路线,防止原列表被意外修改 - 提升效率:将depots转为集合,成员判断时间复杂度从O(n)降至O(1)
- 索引收集更简洁:用列表推导式一次性收集所有depot的索引,替代循环调用
index()(原方法遇到重复depot会出错,优化后支持重复场景) - 遍历方式更直观:用
zip配对连续的索引对,替代原代码中依赖try-except处理索引越界的写法 - 修正逻辑问题:原代码中
random.random()永远不会触发ZeroDivisionError,直接判断值是否为0更合理 - 命名规范:采用符合PEP8的变量与函数命名,提升代码可读性
- 函数解耦:将depots作为参数传入函数,避免依赖全局变量,提升函数复用性
内容的提问来源于stack exchange,提问作者Curious
相关产品推荐
相关产品推荐

