Python组合和产品

时间:2018-12-10 08:19:05

标签: python list combinations product itertools

我有一个数据框列列表:

L=[AA ,  AS  ,  AD  , BB  , BC  , CD ,  CF,CG ]

,我需要所有项目组合,而没有特定的顺序。

但是,在每个组合中,我只能有一个以A开头的名字,但我可以有多个以C开头或没有名字的名字。

关于B,我必须至少有1个B,但可以有更多

所以我需要所有的组合

A=[AA,AS,AD] #only one of these
B=[BB,BC]  #at least one of these
all_others=[CD,CF,CG]  #All, 1, 2 or none of these

到目前为止,我已经有了这段代码;

from itertools import product

for choices in product(['AA','AS','AD',None],['BB', 'BC', None], ['CD','CF', None],):
    print(' '.join(column for column in choices if column))

这有效,但是,它只允许以C开头的一个值,但是我想product C的所有组合。有人能看到我能做的很好的编辑吗?

总结一下;我需要列表中名称的所有组合。根据一条规则,您不能有多个以A开头的变量和多个以B开头的变量

3 个答案:

答案 0 :(得分:1)

当然要表达

all_others=[CD,CF,CG]  #All, 1, 2 or none of these

分解为

all_others=[CD]  #one or none of these
all_others=[CF]  #one or none of these
all_others=[CG]  #one or none of these

然后您的代码变为

from itertools import product

for choices in product(['AA','AS','AD',None],['BB', 'BC', None], ['CD', None], ['CF', None], ['CG', None],):
    print(' '.join(column for column in choices if column))

这处理了这个特定的例子。 但是,如果您有几个以C开头的项目,则可以按以下方法更系统地处理它们:

from itertools import product

for choices in product(['AA','AS','AD',None],['BB', 'BC', None], *product(['CD', 'CF', 'CG'], [None]),):
    print(' '.join(column for column in choices if column))

要解释发生了什么,将['CD', 'CF', 'CG'][None]的乘积得到一个包含以下内容的迭代器

('CD', None), ('CF', None), ('CG', None)

这些正是我们希望传递给product的参数*运算符将迭代器中的元素转换为函数参数。因此,以上两个代码段是等效的。

答案 1 :(得分:1)

尝试以下操作,而不要使用您的for循环:

for choices in itertools.product(['AA','AS','AD',None],['BB', 'BC', None],[' '.join(k) for j in list(itertools.combinations(['CD','CF'],i) for i in range(3)) for k in j]):
    # do what you need

使用print(' '.join(column for column in choices if column))进行选择的输出为:

AA BB
AA BB CD
AA BB CF
AA BB CD CF
AA BC
AA BC CD
AA BC CF
AA BC CD CF
AA
AA CD
AA CF
AA CD CF
AS BB
AS BB CD
AS BB CF
AS BB CD CF
AS BC
AS BC CD
AS BC CF
AS BC CD CF
AS
AS CD
AS CF
AS CD CF
AD BB
AD BB CD
AD BB CF
AD BB CD CF
AD BC
AD BC CD
AD BC CF
AD BC CD CF
AD
AD CD
AD CF
AD CD CF
BB
BB CD
BB CF
BB CD CF
BC
BC CD
BC CF
BC CD CF

CD
CF
CD CF

我建议您将None替换为''或删除它们。

答案 2 :(得分:1)

这是一种更强大/更通用的方式来执行您想要的事情。我首先定义一个辅助函数:

from itertools import combinations, chain, product

def subsets_of_length(s, lengths):
    return chain.from_iterable(combinations(s,l) for l in lengths)

它产生以下输出:

>>>> list(subsets_of_length(['a','b','c'], range(2,4)))
[('a', 'b'), ('a', 'c'), ('b', 'c'), ('a', 'b', 'c')]

>>>> list(subsets_of_length(['d','e'], range(0,2)))
[(), ('d',), ('e',)]

现在,我们要按如下所示合并两个或多个子集

>>>> for choices in product(
         subsets_of_length(['a','b','c'], range(2,4)),
         subsets_of_length(['d','e'], range(0,2)),
     ):
         print(' '.join(str(subset) for subset in choices))

('a', 'b') ()
('a', 'b') ('d',)
('a', 'b') ('e',)
('a', 'c') ()
('a', 'c') ('d',)
('a', 'c') ('e',)
('b', 'c') ()
('b', 'c') ('d',)
('b', 'c') ('e',)
('a', 'b', 'c') ()
('a', 'b', 'c') ('d',)
('a', 'b', 'c') ('e',)

但是我们想将这些元组链接在一起。因此,我们应该做

>>>> for choices in map(chain.from_iterable,product(
         subsets_of_length(['a','b','c'], range(2,4)),
         subsets_of_length(['d','e'], range(0,2)),
     )):
         print(' '.join(column for column in choices if column))

a b
a b d
a b e
a c
a c d
a c e
b c
b c d
b c e
a b c
a b c d
a b c e

针对您所编辑的问题的代码为:

for choices in map(chain.from_iterable,product(
    subsets_of_length(['AA','AS','AD'], [1]),       #only one of these
    subsets_of_length(['BB','BC'], [1,2]),          #at least one of these
    subsets_of_length(['CD','CF','CG'], [0,1,2,3]), #All, 1, 2 or none of these
)):
    print(' '.join(column for column in choices if column))