如何从一组列表中得到笛卡尔积(每一种可能的值组合)?

输入:

somelists = [
   [1, 2, 3],
   ['a', 'b'],
   [4, 5]
]

期望的输出:

[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), (2, 'a', 5), ...]

该技术的一个常见应用是避免深度嵌套循环。有关更具体的重复,请参见避免嵌套for循环。

如果你想要一个相同列表与它自身多次相乘的笛卡尔积,itertools。Product可以很好地处理这个问题。参见对列表中的每对元素的操作或生成具有重复的排列。


当前回答

itertools.product:

import itertools
result = list(itertools.product(*somelists))

其他回答

列表推导式简单明了:

import itertools

somelists = [
   [1, 2, 3],
   ['a', 'b'],
   [4, 5]
]
lst = [i for i in itertools.product(*somelists)]

在Python 2.6及以上版本中,您可以使用'itertools.product '。在旧版本的Python中,你可以从文档中使用以下(几乎——请参阅文档)等效的代码,至少可以作为起点:

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)

两者的结果都是一个迭代器,因此如果您确实需要一个列表进行进一步处理,请使用list(result)。

我相信这是可行的:

def cartesian_product(L):  
   if L:
       return {(a,) + b for a in L[0] 
                        for b in cartesian_product(L[1:])}
   else:
       return {()}
import itertools
>>> for i in itertools.product([1,2,3],['a','b'],[4,5]):
...         print i
...
(1, 'a', 4)
(1, 'a', 5)
(1, 'b', 4)
(1, 'b', 5)
(2, 'a', 4)
(2, 'a', 5)
(2, 'b', 4)
(2, 'b', 5)
(3, 'a', 4)
(3, 'a', 5)
(3, 'b', 4)
(3, 'b', 5)
>>>

这可以用

[(x, y) for x in range(10) for y in range(10)]

另一个变量?没有问题:

[(x, y, z) for x in range(10) for y in range(10) for z in range(10)]