如何找到所有组合

时间:2017-01-24 03:21:01

标签: python loops itertools

如何查找字符串和字母/数字的所有组合,例如: string = StackOverFlow 字母= Z. 组合:

SztackOverFlow
SztzackOverFlow
StzackOverFlow

依此类推......我想要所有的组合。

另一个例子:

string" Dumb"

信" Z"

组合:

DZumb
DZuZmb
DZuZmZb
DuZmZb
DumZb 

我不想要这封信" Z"添加到字符串的末尾或前面" Dumb

我尝试过使用itertools,但我似乎无法用他们的文档弄明白。

我看到的所有解决方案都不是我想要的......它需要生成我在上面发布的组合..

2 个答案:

答案 0 :(得分:4)

这是一个生成器,它使用itertools.product来创建已填充和未填充的插槽的组合,然后将它们与单词的字母一起拉开。

from itertools import product

def inserted(word, ch):
    n = len(word) - 1
    last = word[-1]
    patterns = product(('', ch), repeat=n)
    # skip the initial empty string pattern
    next(patterns)
    for t in patterns:
        yield ''.join([u+v for u,v in zip(word, t)]) + last

word = 'Dumb'
letter = 'Z'
for s in inserted(word, letter):
    print(s)

<强>输出

DumZb
DuZmb
DuZmZb
DZumb
DZumZb
DZuZmb
DZuZmZb

只是为了好玩,这里基本上是相同的算法,但使用二进制计数而不是itertools.product,因此不需要导入。

def inserted(word, ch):
    n = len(word) - 1
    last = word[-1]
    t = ('', ch)
    for i in range(1, 2**n):
        yield ''.join([u + t[int(b)] 
            for b, u in zip('{:0{}b}'.format(i, n), word)]) + last

我认为你会同意我的第一个版本更容易阅读。 :)

答案 1 :(得分:2)

我认为这应该能满足你的需求:[我会尝试更多地优化它]

def combination(word, letter, start=1, end=-1):
    if start >= end:
        return [word]
    else:
        new_word = word[:start] + letter + word[start:]
        output = [new_word, word]
        output.extend(combination(new_word, letter, start+2, end+1))
        output.extend(combination(word, letter, start+1, end))
        return list(set(output))

输出:

combination('dumb', 'z', start=1, end=len('dumb'))

['dzuzmb', 'duzmb', 'dzuzmzb', 'dzumb', 'dzumzb', 'dumzb', 'dumb', 'duzmzb']

如果您不想在返回列表中使用原始单词,那么您可以使用此代码:

def combination(word, letter, start=1, end=-1):
    if start >= end:
        return []
    else:
        new_word = word[:start] + letter + word[start:]
        output = [new_word]
        output.extend(combination(new_word, letter, start+2, end+1))
        output.extend(combination(word, letter, start+1, end))
        return list(set(output))

说明:

递归的基础是:

 if start is >= end: return [No place left to insert letter in word]

 otherwise:
      insert letter at start of the word and call the same method to work on this new word from inserted index +2.

      *+2 because say at index 1 in dumb. We insert letter z as dzumd. Now we don't want to insert another z at dzzumb. So +2.*

      also in the original word just pass it into recursion because we want to work on duzmb. where no z is inserted before u.