如何获取忽略后缀的所有元素组合?

时间:2017-11-20 10:01:26

标签: python performance combinations itertools

我们说我有四个这样的元素

test = ['A', 'B', 'C', 'D']

然后我可以很容易地得到包含这样的三个元素的所有组合

import itertools as it
list(it.combinations(test, 3))

给出了

 [('A', 'B', 'C'), ('A', 'B', 'D'), ('A', 'C', 'D'), ('B', 'C', 'D')]

但是,现在我还有几个后缀,例如

suff = ['x', 'y']

我想考虑一下。我的期望结果看起来像这样

[('A__x', 'B__x', 'C__x'),
 ('A__x', 'B__x', 'C__y'),
 ('A__x', 'B__x', 'D__x'),
 ('A__x', 'B__x', 'D__y'),
 ('A__x', 'B__y', 'C__x'),
 ('A__x', 'B__y', 'C__y'),
 ('A__x', 'B__y', 'D__x'),
 ('A__x', 'B__y', 'D__y'),
 ('A__x', 'C__x', 'D__x'),
 ('A__x', 'C__x', 'D__y'),
 ('A__x', 'C__y', 'D__x'),
 ('A__x', 'C__y', 'D__y'),
 ('A__y', 'B__x', 'C__x'),
 ('A__y', 'B__x', 'C__y'),
 ('A__y', 'B__x', 'D__x'),
 ('A__y', 'B__x', 'D__y'),
 ('A__y', 'B__y', 'C__x'),
 ('A__y', 'B__y', 'C__y'),
 ('A__y', 'B__y', 'D__x'),
 ('A__y', 'B__y', 'D__y'),
 ('A__y', 'C__x', 'D__x'),
 ('A__y', 'C__x', 'D__y'),
 ('A__y', 'C__y', 'D__x'),
 ('A__y', 'C__y', 'D__y'),
 ('B__x', 'C__x', 'D__x'),
 ('B__x', 'C__x', 'D__y'),
 ('B__x', 'C__y', 'D__x'),
 ('B__x', 'C__y', 'D__y'),
 ('B__y', 'C__x', 'D__x'),
 ('B__y', 'C__x', 'D__y'),
 ('B__y', 'C__y', 'D__x'),
 ('B__y', 'C__y', 'D__y')]

所以我想找到两个后缀的所有三个组合,但在这个后缀前面的所有内容都没有重复(例如,我不想要('A__x', 'A__y', 'C__x'),因为会有两个A )。

我目前按如下方式实施:

import itertools as it

def filter_elements(some_elements, connector):

    # get all elements in front of the connector
    all_elements = [eli.split(connector)[0] for eli in some_elements]

    # return True if all elements are unique
    return len(all_elements) == len(set(all_elements))

test = ['A', 'B', 'C', 'D']

suff = ['x', 'y']

connector = '__'

test_suff = ["{}{}{}".format(eli, connector, si) for eli in test for si in suff]

all_combinations = list(it.combinations(test_suff, 3))

desired_combinations = [combi for combi in all_combinations if filter_elements(combi, connector)]

给了我想要的输出。

显然,这不仅适用于四个元素和两个后缀,而且适用于任意组合。有没有更直接的方法来实现这一点,避免创建all_combinations

1 个答案:

答案 0 :(得分:3)

我认为您只需要it.product

>>> list(it.product('xy', repeat=3))
[('x', 'x', 'x'),
 ('x', 'x', 'y'),
 ('x', 'y', 'x'),
 ('x', 'y', 'y'),
 ('y', 'x', 'x'),
 ('y', 'x', 'y'),
 ('y', 'y', 'x'),
 ('y', 'y', 'y')]

所以如果你想要上面列出的32个元组:

list(it.product(it.combinations(test, 3), it.product(suff,repeat=3)))

它返回:

[(('A', 'B', 'C'), ('x', 'x', 'x')),
 (('A', 'B', 'C'), ('x', 'x', 'y')),
 (('A', 'B', 'C'), ('x', 'y', 'x')),
 (('A', 'B', 'C'), ('x', 'y', 'y')),
 (('A', 'B', 'C'), ('y', 'x', 'x')),
 (('A', 'B', 'C'), ('y', 'x', 'y')),
 (('A', 'B', 'C'), ('y', 'y', 'x')),
 (('A', 'B', 'C'), ('y', 'y', 'y')),
 (('A', 'B', 'D'), ('x', 'x', 'x')),
 (('A', 'B', 'D'), ('x', 'x', 'y')),
 (('A', 'B', 'D'), ('x', 'y', 'x')),
 (('A', 'B', 'D'), ('x', 'y', 'y')),
 (('A', 'B', 'D'), ('y', 'x', 'x')),
 (('A', 'B', 'D'), ('y', 'x', 'y')),
 (('A', 'B', 'D'), ('y', 'y', 'x')),
 (('A', 'B', 'D'), ('y', 'y', 'y')),
 (('A', 'C', 'D'), ('x', 'x', 'x')),
 (('A', 'C', 'D'), ('x', 'x', 'y')),
 (('A', 'C', 'D'), ('x', 'y', 'x')),
 (('A', 'C', 'D'), ('x', 'y', 'y')),
 (('A', 'C', 'D'), ('y', 'x', 'x')),
 (('A', 'C', 'D'), ('y', 'x', 'y')),
 (('A', 'C', 'D'), ('y', 'y', 'x')),
 (('A', 'C', 'D'), ('y', 'y', 'y')),
 (('B', 'C', 'D'), ('x', 'x', 'x')),
 (('B', 'C', 'D'), ('x', 'x', 'y')),
 (('B', 'C', 'D'), ('x', 'y', 'x')),
 (('B', 'C', 'D'), ('x', 'y', 'y')),
 (('B', 'C', 'D'), ('y', 'x', 'x')),
 (('B', 'C', 'D'), ('y', 'x', 'y')),
 (('B', 'C', 'D'), ('y', 'y', 'x')),
 (('B', 'C', 'D'), ('y', 'y', 'y'))]

要获得所需的格式,您需要使用zipjoin

[tuple('__'.join(ls) for ls in zip(*t)) for t in it.product(it.combinations(test, 3), it.product(suff,repeat=3))]

它返回:

[('A__x', 'B__x', 'C__x'),
 ('A__x', 'B__x', 'C__y'),
 ('A__x', 'B__y', 'C__x'),
 ('A__x', 'B__y', 'C__y'),
 ('A__y', 'B__x', 'C__x'),
 ('A__y', 'B__x', 'C__y'),
 ('A__y', 'B__y', 'C__x'),
 ('A__y', 'B__y', 'C__y'),
 ('A__x', 'B__x', 'D__x'),
 ('A__x', 'B__x', 'D__y'),
 ('A__x', 'B__y', 'D__x'),
 ('A__x', 'B__y', 'D__y'),
 ('A__y', 'B__x', 'D__x'),
 ('A__y', 'B__x', 'D__y'),
 ('A__y', 'B__y', 'D__x'),
 ('A__y', 'B__y', 'D__y'),
 ('A__x', 'C__x', 'D__x'),
 ('A__x', 'C__x', 'D__y'),
 ('A__x', 'C__y', 'D__x'),
 ('A__x', 'C__y', 'D__y'),
 ('A__y', 'C__x', 'D__x'),
 ('A__y', 'C__x', 'D__y'),
 ('A__y', 'C__y', 'D__x'),
 ('A__y', 'C__y', 'D__y'),
 ('B__x', 'C__x', 'D__x'),
 ('B__x', 'C__x', 'D__y'),
 ('B__x', 'C__y', 'D__x'),
 ('B__x', 'C__y', 'D__y'),
 ('B__y', 'C__x', 'D__x'),
 ('B__y', 'C__x', 'D__y'),
 ('B__y', 'C__y', 'D__x'),
 ('B__y', 'C__y', 'D__y')]