Python:以代数方式连接列表列表

时间:2014-02-10 16:08:12

标签: python list itertools

在数学中,当你有两组单词 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并接受任何大小的定义?

3 个答案:

答案 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)时间复杂度非常残酷。

引用documentation

  

对于某些用例,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]