简体   繁体   English

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

[英]How to get all combinations with no repeats?

So, I started off with this array: 所以,我从这个数组开始:

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

And I played around for a little while before getting python to print each unique, non-repeating combination, like so: 我玩了一段时间,然后让python打印每个唯一的,非重复的组合,如下所示:

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

But now, I'd like to take all of these into a new array: 但是现在,我想将所有这些都放入一个新数组中:

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

And print all 3-element-long combinations, not including rearrangements, that have no repeats. 并打印所有没有重复的三元素长的组合,不包括重排。

What I mean by 'no repeats': 我的意思是“不重复”:

AB , CD and EF is a 3-element long combination with no repeats, but AB , BD and EF is a 3-element-long combination with repeats, as 'B' appears in both 'AB' and ' BD' . ABCDEF是3个元素长的组合,没有重复,但是ABBDEF是3个元素长的组合,有重复,因为'AB'和' BD'中都出现'B' BD'

What I mean by 'not including rearrangements': 我的意思是“不包括重新排列”:

AB, CD, EF would be the same as BA, DC, FE, because all of the 2-letter elements are the same (BA is AB rearranged, DC is CD rearranged, and FE is EF rearranged). AB,CD,EF与BA,DC,FE相同,因为所有2个字母的元素都相同(BA重排了AB,DC重排了CD,FE重排了EF)。 So ideally it'd print something like: 因此,理想情况下,它将打印如下内容:

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,

I believe those are all the combinations where no 2-letter element is repeated. 我相信所有这些组合都不会重复2个字母的元素。

How would I go about printing this? 我将如何进行打印? Thanks! 谢谢!

Generator based recursive approach (without any 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']]

This takes the first element, pairs it with each of the other elements, and combines the resulting pair with every exhaustive pair list that can be made from the remaining elements. 这将获取第一个元素,将其与其他每个元素配对,然后将结果对与可以从其余元素组成的每个详尽对列表进行组合。 The base case is when there are only two elements. 基本情况是只有两个元素时。

Note: The assembling of rest presupposes that there are no repetitions in the initial string/sequence. 注意: rest的组装以初始字符串/序列中没有重复为前提。

Here's a brute-force non-recursive version using itertools . 这是使用itertools的蛮力非递归版本。 It generates the pairs, and then makes all the combinations from those pairs, using sets to eliminate combinations that repeat any letters. 它生成对,然后使用这些对消除重复任何字母的组合,从这些对中进行所有组合。 It's much less efficient than schwobaseggl's generator, but it's still reasonably fast for small strings because combinations is very fast. 它的效率比schwobaseggl的生成器低得多,但是对于小型字符串,它仍然相当快,因为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)

output 产量

('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')

On my 2GHz machine it takes around 13 seconds to print the 945 results for pairs('ABCDEFGHIJ') . 在我的2GHz机器上,大约需要13秒才能打印出945个结果pairs('ABCDEFGHIJ') In comparison, schwobaseggl's comb only takes 0.193 seconds. 相比之下,schwobaseggl的comb仅需0.193秒。 :) :)


Here's a smarter itertools version. 这是一个更智能的itertools版本。 This one still does more work than is necessary, but it's only about twice as slow as schwobaseggl's comb generator. 这仍然需要做更多的工作,但是它的速度仅为schwobaseggl的comb发生器的两倍。 We first produce combinations of half the size of the original string, and use set.difference to produce the complementary combination. 我们首先产生原始字符串大小一半的组合,然后使用set.difference产生互补组合。 We then permute that combination to combine it with the original combination. 然后,我们置换该组合以将其与原始组合合并。

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)]

A faster variation on PM 2Ring's code: 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM