Python代码优化:如何避免遗传算法交叉实现中的过多索引?
嘿,作为Python新手能上手遗传算法的交叉操作已经超棒啦!那些层层嵌套的selected_parents[0][0][indeces[i][0][0]]索引确实看着头大,咱们来把代码简化得清爽又易读~
首先,咱们先搞定最烦人的嵌套数组问题:你的selected_parents里每个元素都是二维numpy数组(比如array([[4,6,...]])),所以才需要多层索引才能拿到具体元素。咱们可以先把它们转成一维数组,瞬间告别多层嵌套:
import numpy as np # 原始父代数据 selected_parents = [np.array([[4, 6, 3, 1, 0, 7, 5, 2]]), np.array([[0, 2, 7, 3, 5, 4, 1, 6]])] # 转成一维数组,索引直接用parent1[i]就行 parent1 = selected_parents[0].ravel() # ravel返回原数组的视图,更高效;flatten返回副本,按需选 parent2 = selected_parents[1].ravel()
接下来,咱们把交叉逻辑拆成两个小函数,让代码结构更清晰:
1. 提取父代的较长子串
根据你的需求,后代要继承父代的较长子串,咱们写个函数专门处理这个判断:
def get_longer_substring(parent, co_point): """获取切割后父代的较长子串""" parent_len = len(parent) # 判断前co_point个元素更长,还是后(parent_len - co_point)个更长 if co_point > parent_len - co_point: return parent[:co_point] else: return parent[co_point:]
2. 生成后代
接下来写生成后代的函数:先拿到要保留的子串,再从另一个父代里按顺序筛选出不在保留子串里的元素,填充到剩余位置:
def create_offspring(parent_kept, parent_fill, co_point): """根据保留父代和填充父代生成后代""" kept_sub = get_longer_substring(parent_kept, co_point) # 把保留子串转成集合,提升"in"操作的效率(长序列更明显) kept_set = set(kept_sub) # 按顺序筛选填充父代中不在保留子串里的元素 fill_elements = [x for x in parent_fill if x not in kept_set] # 计算需要填充的元素数量 need_fill = len(parent_kept) - len(kept_sub) # 根据保留子串的位置组合后代:前半部分保留就填后面,后半部分保留就填前面 if len(kept_sub) == co_point: return np.concatenate([kept_sub, fill_elements[:need_fill]]) else: return np.concatenate([fill_elements[:need_fill], kept_sub])
完整示例运行
用你给出的切割点co_point=5测试一下:
co_point = 5 crossed_p1 = create_offspring(parent1, parent2, co_point) crossed_p2 = create_offspring(parent2, parent1, co_point) print("crossed_p1:", crossed_p1) # 输出: [4 6 3 1 0 2 7 5] print("crossed_p2:", crossed_p2) # 输出: [0 2 7 3 5 4 6 1]
这样代码完全没有多层索引,逻辑也一目了然:
- 先扁平化数组,解决嵌套索引的问题
- 拆分函数让每个模块只做一件事,后期修改或者扩展都很方便
- 用集合优化筛选效率,长序列场景下速度更快
内容的提问来源于stack exchange,提问作者RezAm
相关产品推荐
相关产品推荐

