python 中的部分列表,索引有问题

parts of lists in python, troubles with indexes

我是 python 的新手,列表和索引给我带来了一些麻烦。

我想做的是: ', 获取代表 RPN 表达式的两个个体,个体 1 和个体 2 作为示例:

i1=['3', 'x', '*', '3' ,'4' ,'*', '/']
i2=['x', '4', '/', 'x' ,'4' ,'+', '-']

然后,获取它们的子集并交换子集,如下所示:

我从 i1 中获取子集 ['3','4','*'] 并从 i2 ['4'](最后的 3)中获取子集,然后交叉生成两个输出:

out1=['3', 'x', '*','4' , '/']
out2=['x', '3' ,'4' ,'*', '/', 'x' ,'6' ,'+', '-']

我做的代码如下,它一直给我错误的结果,比如差一个错误,我不想进入 for 循环路线,因为我敢打赌还有更多 pythonesque 方式这样做。谁能帮我一把?

def crossover(individual1,individual2,treedepth):
    from commonfunctions import getDepth,traverse,get_random_operator
    from commonfunctions import isOperator
    from generators import generate_RPN_expr
    #simple element mutation
    cxposindividual1 = random.randint(0, len(individual1) - 1)
    cxposindividual2 = random.randint(0, len(individual2) - 1)

    subtree1=traverse(individual1,cxposindividual1)
    subtree2 = traverse(individual2, cxposindividual2)
    individual1depth=getDepth(individual1)
    individual2depth = getDepth(individual2)
    subtree1depth=getDepth(subtree1)
    subtree2depth = getDepth(subtree2)


    output1=list()
    output1[:]=[]

    output2=list()
    output2[:]=[]


    #todo debug this !!!!

    #verificar se ecsolhemos um operador ou um nó terminal
    output1 = individual1[:len(individual1)+1-cxposindividual1-len(subtree1)]+subtree2+individual1[len(individual1)-cxposindividual1+1:]
    output2 = individual2[:len(individual2) + 1 - cxposindividual2 - len(subtree2)] + subtree1 + individual2[len(individual2) - cxposindividual2 + 1:]

    if len(output1) == 2 or len(output2) == 2:
        print('argh>>>') # problema !!!!

    #print ('CX')
    return (output1,output2)

遍历函数returns选中位置的子树。 getDepth 尚未使用。

谢谢

豪尔赫


新代码


def crossover(individual1,individual2,treedepth):
    from commonfunctions import getDepth,traverse,get_random_operator,traverse_with_indexes
    from commonfunctions import isOperator

    r1 = random.randrange(len(individual1))
    r2 = random.randrange(len(individual2))

    st1 = traverse(individual1, r1)
    st2 = traverse(individual2, r2)

    slice1 = slice(r1, r1+len(st1))
    slice2 = slice(r2, r2+len(st2))


    i1,i2 = individual1[:],individual2[:]
    a,b=i1[slice1],i2[slice2]
    i1[slice1],i2[slice2] = i2[slice2],i1[slice1]

    return i1, i2

这里,个人 1 等于 ['3.8786681846845', 'x', '+'] 和 st1 = ['x'] 切片是 2,3 我认为它应该是 1,2但 ... 其中个人 2 = ['x'] st2 = ['x'] 切片是 0,1 很好 !!!
我很想用 sizesfor exceptions 制作一些 if 块,但我不喜欢 exceptions

谢谢

我怀疑您的问题是因为 python 中的 切片 不包含它们的最终索引。也就是说,[0:1] 是一个只包含一个元素 [0] 的切片。

你的例子:

i1=['3', 'x', '*', '3' ,'4' ,'*', '/']
i2=['x', '4', '/', 'x' ,'4' ,'+', '-']
#    0    1    2    3    4    5    6

然后:

temp1 = i1[3:6]   # 3,4,*  
temp2 = i2[1:2]   # 4

然后:

print(i1)
print(i2)

i1[3:6] = temp2
i2[1:2] = temp1

print(i1)
print(i2)

最后,因为牛逼,你可以这样做:

i1[3:6],i2[1:2] = i2[1:2],i1[3:6]

或者这样:

A = slice(3,6)
B = slice(1,2)

i1[A],i2[B] = i2[B],i1[A]

编辑

更进一步,您可以使用 random.randrange() 来避免 fencepost 错误,并执行以下操作:

def crossover(individual1,individual2,treedepth):

    r1 = random.randrange(len(individual1))
    r2 = random.randrange(len(individual2))

    st1 = traverse(individual1, r1)
    st2 = traverse(individual2, r2)

    slice1 = slice(r1, r1+len(st1))
    slice2 = slice(r2, r2+len(st2))

    # fazer pseudonimos 
    i1,i2 = individual1,individual2
    # o fazer copias
    i1,i2 = individual1[:],individual2[:]

    i1[slice1],i2[slice2] = i2[slice2],i1[slice1]

    return i1, i2

遍历函数

这个函数的目的是return从位置start开始的'有意义的子树,(因为程序是一个rpn表示)

def traverse(inputexpr,start):
    from copy import copy,deepcopy
    components=list()
    components[:]=[]
    components=inputexpr[0:len(inputexpr)-start+1]
    components.reverse()
    pos=0
    result=list()
    result[:]=[]
    score=0
    if isOperator(components[pos]):
        result.append(components[pos])
        score=score+getArity(components[pos])
    else:
        result.append(components[pos])
        score=score -1
    pos=pos+1
    while score>0:
        if isOperator(components[pos]):
            result.append(components[pos])
            score = score + getArity(components[pos])-1
        else:
            result.append(components[pos])
            score = score - 1
        pos = pos + 1
    result.reverse()
    return result

第二次编辑

考虑这个重新实现。这是否符合您的要求?

_Arity = {op:2 for op in '*/+-%'}

def getArity(op):
    return _Arity[op] if op in _Arity else 0

def isOperator(op):
    return op in _Arity

def traverse(inputexpr, pos):
    """
    Return the meaningful subtree of inputexpr that has its upper node
    at position pos. Given an input like this:

        [ A, B, +, 5, * ]
        # 0  1  2  3  4

    Here are the expected results:

        0:  [ A ]
        1:  [ B ]
        2:  [ A B + ]
        3:  [ 5 ]
        4:  [ A B + 5 * ]

    """
    chop = pos + 1
    subtree = inputexpr[:chop]
    score = 1
    while score:
        chop -= 1
        score += getArity(subtree[chop]) - 1

    return subtree[chop:]

i1=['3', 'x', '*', '3' ,'4' ,'*', '/']
i2=['x', '4', '/', 'x' ,'4' ,'+', '-']

for i in range(len(i1)):
    print("#: {}, subtree= {}".format(i, traverse(i1, i)))

终于按预期工作了

#output tree
output1=list()
output1[:]=[]

output2=list()
output2[:]=[]

i1p1 = individual1[:len(individual1) - len(subtree1) - cxposindividual1]
i1p2 = subtree2
i1p3 = individual1[len(i1p1) + len(subtree1):]

i2p1 = individual2[:len(individual2) - len(subtree2) - cxposindividual2]
i2p2 = subtree1
i2p3 = individual2[len(i2p1) + len(subtree2):]


output1=i1p1+i1p2+i1p3
output2=i2p1+i2p2+i2p3

非常感谢 Austin,多亏了你,我发现了困扰我其他 bug 的 bug。 让它工作后,我将以更 python 风格的方式实现它。 现在我正在使用这个非常冗长的代码,所以我不会在语言细节中得到很多。

再次感谢