如何获得没有重复的所有组合?

时间:2017-11-19 19:06:07

标签: python arrays combinations

所以,我开始使用这个数组:

array = ['A', 'B', 'C', 'D', 'E', 'F']

在让python打印每个独特的非重复组合之前,我玩了一会儿,如下所示:

AB,
AC,
AD,
AE,
AF,
BC,
BD,
BE,
BF,
CD,
CE,
CF,
DE,
DF,
EF,

但是现在,我想将所有这些变成一个新阵列:

array2 = ['AB', 'AC', 'AD'...., 'EF']

打印所有没有重复的3元素长组合,不包括重排。

我的意思是'没有重复':

ABCDEF是一个3元素的长组合,没有重复,但ABBDEF是一个3元素长的重复组合,'B'出现在' AB'和' BD'

我的意思是'不包括重新排列':

AB,CD,EF与BA,DC,FE相同,因为所有2个字母的元素都相同(BA重新排列AB,DC重新排列CD,FE重新排列EF)。理想情况下,它打印的内容如下:

AB CD EF,
AB CE DF,
AB CF DE,
AC BD EF,
AC BE DF,
AC BF DE,
AD BC EF,
AD BE CF,
AD BF CE,
AE BC DF,
AE BD CF,
AE BF CD,
AF BC DE,
AF BD CE,
AF BE CD,

我相信这些都是没有重复2个字母元素的组合。

我该如何打印?谢谢!

3 个答案:

答案 0 :(得分:2)

基于

Generator的递归方法(没有任何itertools):

def comb(s):
  if len(s) == 2:
    yield [s]
  for x in s[1:]:
    first = ''.join((s[0], x))
    rest = ''.join(c for c in s if c not in first)
    for com in comb(rest):
      yield [first] + com

>>> list(comb('ABCDEF'))
[['AB', 'CD', 'EF'],
 ['AB', 'CE', 'DF'],
 ['AB', 'CF', 'DE'],
 ['AC', 'BD', 'EF'],
 ['AC', 'BE', 'DF'],
 ['AC', 'BF', 'DE'],
 ['AD', 'BC', 'EF'],
 ['AD', 'BE', 'CF'],
 ['AD', 'BF', 'CE'],
 ['AE', 'BC', 'DF'],
 ['AE', 'BD', 'CF'],
 ['AE', 'BF', 'CD'],
 ['AF', 'BC', 'DE'],
 ['AF', 'BD', 'CE'],
 ['AF', 'BE', 'CD']]

这将获取第一个元素,将其与每个其他元素配对,并将结果对与可以从其余元素制作的每个穷举对列表组合。基本情况是只有两个元素。

注意: rest的汇编预先假定初始字符串/序列中没有重复。

答案 1 :(得分:1)

这是使用itertools的强力非递归版本。它生成对,然后使用集合来制作这些对的所有组合,以消除重复任何字母的组合。它比 效率低,但对于小字符串它仍然相当快,因为​​combinations非常快。

from itertools import combinations

def pairs(s):
    n = len(s)
    numgroups = n // 2
    for v in combinations(map(''.join, combinations(s, 2)), numgroups):
        if len(set(i for u in v for i in u)) == n:
            yield v

for t in pairs('ABCDEF'):
    print(t)

<强>输出

('AB', 'CD', 'EF')
('AB', 'CE', 'DF')
('AB', 'CF', 'DE')
('AC', 'BD', 'EF')
('AC', 'BE', 'DF')
('AC', 'BF', 'DE')
('AD', 'BC', 'EF')
('AD', 'BE', 'CF')
('AD', 'BF', 'CE')
('AE', 'BC', 'DF')
('AE', 'BD', 'CF')
('AE', 'BF', 'CD')
('AF', 'BC', 'DE')
('AF', 'BD', 'CE')
('AF', 'BE', 'CD')

在我的2GHz机器上,打印pairs('ABCDEFGHIJ')的945结果大约需要13秒。相比之下,schwobaseggl的comb只需要0.193秒。 :)

这是一个更智能的itertools版本。这个仍然比必要的工作更多,但它只是schwobaseggl的comb发生器的两倍慢。我们首先生成原始字符串大小的一半的组合,并使用set.difference来生成互补组合。然后我们将该组合置换为与原始组合相结合。

from itertools import combinations, permutations

def pairs(s):
    a = set(s)
    for u in combinations(s, len(s) // 2):
        b = tuple(sorted(a.difference(u)))
        if b < u:
            break
        for v in permutations(b):
            c = [*zip(u, v)]
            if all(i<j for i, j in c):
                yield [*map(''.join, c)]

答案 2 :(得分:0)

PM 2Ring代码的更快变化:

from itertools import combinations
array = ['A', 'B', 'C', 'D', 'E', 'F']
n = len(array)
numgroups = n // 2

array2 = map(''.join, combinations(array,2))
result = (' '.join(com) for com in combinations(array2,numgroups) if len(set(''.join(com)))==n)
for res in result:
    print res