在数学中,当你有两组单词 A = {foo,bar} 和 B = {x,y} 时,那么代数(或每个 - 每个产品是 AB = {foox,fooy,barx,bary} 。我想在Python中使用类似的东西。给出两组单词(=列表列表):
A = [ [0,1], [2,3] ]
B = [ [4,5], [6,7] ]
我想将它们连接在一起:
AB = [ [0,1,4,5], [0,1,6,7], [2,3,4,5], [2,3,6,7] ]
这本身并不困难,可以使用product
:
AB = [ a+b for (a,b) in itertools.product(A,B) ]
但是,我有一个“集合”列表(又名列表清单)
A = [ [0,1], [2,3] ]
B = [ [4,5], [6,7] ]
C = [ [4,5], [6,7] ]
SETS = [A,B,C]
现在我可以手动
ABC = [ a+b+c for (a,b,c) in itertools.product(A,B,C) ]
但如果我有20套连接,我不能这样做。那么,如何编写ABC
的定义,只使用SETS
并接受任何大小的定义?
答案 0 :(得分:7)
ABC = [ sum(z, []) for z in itertools.product(*SETS) ]
product(*SETS)
基本上是product(A, B, C)
。技术术语是argument unpacking。
sum(z, [])
基本上是a + b + c + []
。
修改强>:
聪明的人在评论中说sum
不是加入列表列表的最佳方式。 O(n ^ 2)时间复杂度非常残酷。
对于某些用例,sum()有很好的替代方法。该 首选,快速连接字符串序列的方法是通过调用 ''。加入(序列)。要使用扩展名添加浮点值 精度,请参见math.fsum()。要连接一系列迭代, 考虑使用itertools.chain()。
那更好:
from itertools import chain, product
ABC = [ list(chain(*z)) for z in product(*SETS) ]
或者,如果两个参数解包是一个解包过多的参数:
ABC = [ list(chain.from_iterable(z)) for z in product(*SETS) ]
或者,如果你进入map
:
ABC = map(list, map(chain.from_iterable, product(*SETS)))
答案 1 :(得分:1)
使用参数解包,您可以抽象集合的数量:itertools.product(*SETS)
。此外,您可以定义一个辅助函数来连接可变数量的列表(高效):
def concat(seqs):
result = []
for seq in seqs:
result.extend(seq)
return result
总结:[concat(prod) for prod in itertools.product(*SETS)]
答案 2 :(得分:1)
首先,使用*
运算符为SETS
函数参数解包itertools.product()
。
itertools.product(*SET)
然后使用import operator
连接结果:
product = [ reduce(operator.add, tuple) for tuple in itertools.product(*SET) ]
这是有效的,因为如果tuple
变量为([0,1], [4,5], [8,9])
,reduce(operator.add, tuple)
仍会为您提供[0,1,4,5,8,9]
。