为什么这个庞奈特方格失败了?

2 投票
3 回答
866 浏览
提问于 2025-04-17 12:19

这是我程序的一部分,用来生成杂交方格。它应该把一种形式为 [['A','a'],['b','b'],['C','C']...] 的“基因组”分离成可能的配子:

def gene_erator2(gen):
    gam = [[], []]
    q = 0
    for x in gen:
        q = q + 1
        if q > 1:
            gamgam = gam[:]
            for z in gam: 
                gamgam.append(z)
            gam = gamgam[:]
        for y in range(len(gam)):
            if y < len(gam)/2:
                gam[y].append(x[0])
            else:
                gam[y].append(x[1])
    return gam

当我执行

gene_erator2([['A','a'], ['B','b'], ['X','Y']])

时,我得到的是

[['A', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['a', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['A', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['a', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['A', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['a', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['A', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['a', 'B', 'b', 'X', 'X', 'Y', 'Y']]

而不是我期待的

[['A', 'B', 'X'], ['a', 'B', 'X'], ['A', 'b', 'X'], ['a', 'b', 'X], ['A', 'B', 'Y'], ['a', 'B', 'Y'], ['A', 'b', 'Y'], ['a', 'b', 'Y']]

....这是什么?我说,这到底是什么?

编辑:现在我知道了一个能实现我想要功能的函数,感谢Shang,但我还是想知道我的代码出了什么问题....

3 个回答

1

除了shang提供的最佳解决方案外,你的代码中还有很多错误。以下是一些问题:

I

     gamgam = gam[:]
    for z in gam: 
        gamgam.append(z)
    gam = gamgam[:]

我认为这里是对gam列表的重复使用,但在gamgam.append(z)这一行,你实际上是把同一个子列表的另一个引用添加进去了,所以结果会包含很多对最初子列表的引用。

II

更新:这并不是一个错误,因为在循环过程中gam的大小并没有增加

 if y < len(gam)/2:

在这种情况下,len(gam)会随着你向gam添加元素而增加,所以它不会像你想的那样工作。

所以尽管整个解决方案看起来不太美观,但只要修正这两个问题,这段代码就能正常工作:

def gene_erator2(gen):
    gam = [[], []]
    q = 0
    for x in gen:
        q = q + 1
        if q > 1:
            gamgam = gam[:]
            for z in gam:
                gamgam.append(z[:])
            gam = gamgam[:] 
        lenGam = len(gam)
        for y in range(lenGam):
            if y < lenGam/2:
                gam[y].append(x[0])
            else:
                gam[y].append(x[1])
    return gam

更新: 根据要求,这是对itertools.product的一种python风格的重写:

def product(collections):
    if collections:
        for subproduct in product(collections[1:]):
            for element in collections[0]:
                yield list(element) + subproduct

    else: yield []

def gene_erator2(gen): return list(product(gen))

此外,在这种情况下,建议使用元组而不是列表。

1

还有一种解决这个问题的方法,不用 itertools.product

def gene_erator2(args):
    result = [[]]
    for pool in args:
        result = [x+[y] for x in result for y in pool]
    return result

另外,可以看看 itertools.product文档

4

标准库里有一个函数可以满足你的需求。

import itertools

def gene_erator2(gen):
    return itertools.product(*gen)

这个函数会返回一个迭代器,迭代器可以让你遍历所有的组合。

>>> i = gene_erator2([['A','a'],['B','b'],['X','Y']])
>>> list(i)
[('A', 'B', 'X'), ('A', 'B', 'Y'), ('A', 'b', 'X'), ('A', 'b', 'Y'), ('a', 'B', 'X'), ('a', 'B', 'Y'), ('a', 'b', 'X'), ('a', 'b', 'Y')]

撰写回答