列表的排列组合

1 投票
2 回答
1592 浏览
提问于 2025-04-18 12:15

假设我们有一个包含多个列表的列表。每个列表里面可以有任意数量的元素。例如 [[1,2,3,4],[2,3],[4,5,6,7],[1]]。我想生成这些列表的所有可能排列,其中每次排列只能从最里面的列表中选择一个元素。所以输出的结果会是 [1,2,4,1]、[1,3,4,1] 等等。

示例输入 = [[1,2],[3],[4]]
示例输出 = [[1,3,4],[2,3,4]]

我之前尝试过一些代码,但逻辑有问题。以下是我正在进行的代码,目前卡住了。我不知道该怎么继续下去。对于排列和组合,我不是很擅长。

我尝试的内容和上面描述的一样,只不过这里的最里面的元素是一些坐标。

[[[1,2],[2,4]],[[2,3],[4,2]],[[1,5]],[[3,3],[7,2],[5,6]]]
def perm(a,length):
    arr=[]
    k=0
    while (k<length):
        temp=[]
        for i in a:


a=[[[1,2],[2,4]],[[2,3],[4,2]],[[1,5]],[[3,3],[7,2],[5,6]]]
perm(a)

如果需要进一步的解释,请告诉我。任何帮助都非常感谢。

编辑

我希望能得到一个不使用 itertools 或其他类似 Python 模块的解决方案。我应该早点提到这一点。否则这是一个有效且非常方便的解决方案。

伪代码逻辑或简单的解决思路就可以,不用使用 Python 库。抱歉这么晚才补充这个细节。

2 个回答

2

我觉得下面这个递归版本比用列表推导式写的更容易理解,不过这可能只是个人喜好问题:

def cartesianProduct( *lists ) :
    if not lists : # nothing to do, yield empty tuple
        yield ()
    else : # let's do A x cartesianProduct( B x C x ... )
        for a in lists[0] : # each element of A
            for tup in cartesianProduct( *lists[1:] ) : # each tuple of ( B x C x ... )
                yield ( a, ) + tup # concatenate and yield 

list( product( 'AB', range(3), 'xy' ) ) == list( cartesianProduct('AB', range(3), 'xy') )

True 
2

你可以很简单地使用 itertools.product 来实现这个功能:

>>> from itertools import product
>>> list(product(*[[1,2],[3],[4]]))
[(1, 3, 4), (2, 3, 4)]
>>> list(product(*[[1,2,3,4],[2,3],[4,5,6,7],[1]]))
[(1, 2, 4, 1), (1, 2, 5, 1), (1, 2, 6, 1), (1, 2, 7, 1), 
 (1, 3, 4, 1), (1, 3, 5, 1), (1, 3, 6, 1), (1, 3, 7, 1), 
 (2, 2, 4, 1), (2, 2, 5, 1), (2, 2, 6, 1), (2, 2, 7, 1), 
 (2, 3, 4, 1), (2, 3, 5, 1), (2, 3, 6, 1), (2, 3, 7, 1), 
 (3, 2, 4, 1), (3, 2, 5, 1), (3, 2, 6, 1), (3, 2, 7, 1), 
 (3, 3, 4, 1), (3, 3, 5, 1), (3, 3, 6, 1), (3, 3, 7, 1), 
 (4, 2, 4, 1), (4, 2, 5, 1), (4, 2, 6, 1), (4, 2, 7, 1), 
 (4, 3, 4, 1), (4, 3, 5, 1), (4, 3, 6, 1), (4, 3, 7, 1)]

根据文档,这里有一个几乎等效的实现方式,不需要任何 import

def product(*args, **kwds):
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
    pools = map(tuple, args) * kwds.get('repeat', 1)
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)

撰写回答