从两个相同长度的列表中按顺序生成新的子列表,没有重复并在随机索引处拆分

问题描述

在这个问题中,我试图从两个长度为 n 的列表中创建一个长度为 n 的新列表。我随机选择第一个父列表的一个子集(使用开始和结束变量)并将它们添加到新列表中它们出现在相应列表中的相同位置。然后我用第二个父列表中的元素按照它们出现的顺序填充新列表的其余部分,而不复制从第一个父列表中选择的任何元素。图片说明了这一点。

enter image description here

这是我的 python 代码:这里的平面是感知器模型的权重。

def breed(plane1,plane2):
    num_list = list(range(0,len(plane1)))
    random.shuffle(num_list)
    n1 = num_list[0]
    n2 = num_list[1]
    
    start = min(n1,n2)
    end = max(n1,n2)

    child = [None] * len(plane1)
    for i in range(start,end):
        child[i] = plane1[i]

    idx = (end) % len(plane2)   
    for i in range(len(plane2)):
        pos = (end + i) % len(plane2)

        if plane2[pos] not in child:
            child[idx] = plane2[pos]
            idx = (idx + 1) % len(plane2)

    return child

谁能推荐一种高效简洁的不同方式?

另外,随机范围的末端不包括在选择中:

one = [1,2,3,4,5,6,7,8,9]
two = [9,1]
child = breed(one,two)
print(child)

开始:0 结束:7

输出: [1,9,8]

解决方法

这是一个解决方案。它可能会更好,不使用 while 循环会更优雅。我不知道它是否涵盖所有边缘情况。我已经将逻辑从随机生成的数字中分离出来,以便于测试。

import random


def breed(plane1,plane2):
    assert len(plane1) == len(plane2)
    istart = random.randint(0,len(plane1) - 2)
    iend = random.randint(istart + 1,len(plane1) - 1)
    print(f"random indices: {istart} to {iend}")
    return generate_breed(plane1,plane2,istart,iend)


def generate_breed(plane1,iend):
    child = [-1 for _ in plane1]
    child[istart : iend + 1] = plane1[istart : iend + 1]
    i = j = 0
    while True:
        if j == istart:
            j = iend + 1
        if j >= len(child):
            break
        if plane2[i] not in child:
            child[j] = plane2[i]
            j += 1
        i += 1
    return child


if __name__ == "__main__":
    p1,p2 = [1,2,3,4,5,6],[7,1,6]
    start,end = 2,4
    assert generate_breed(p1,p2,start,end) == [7,1]
    assert generate_breed([1,3],[4,1],2) == [1,3]

    # call like this,but answer is unpredictable due to randint call
    print(breed([1,1]))

,

编辑

最初的答案是超级错误的,经过一段时间的迭代后,这有效,假设列表本身没有重复项。

幻数

通过生成开始和结束,如果您想设置最小长度,可以调整魔力 -2 和魔力 +1。我在这里将最小长度设置为 1。

def breed(plane1,plane2):
    i = randint(0,len(plane1) - 2)
    j = randint(i + 1,len(plane1))

    plane2 = [x for x in plane2 if x not in plane1[i:j]]
    child = plane2[0:i] + plane1[i:j] + plane2[i:len(plane1) - (j - i)]
    return child