改变3个地方的所有组合

All combinations by changing 3 places

这是代码

from itertools import combinations, product

string = "abcd012345"

char = "01268abc"

for i, j in combinations(tuple(range(len(string))), 2):
    for char1, char2 in product(char, char):
        print(string[:i] + char1 + string[i+1:j] + char2 + string[j+1:])

我们有一个字符串 abcd012345 ,我们改变两个地方以获得所有可能的组合。在这个例子中我们使用char 一组可以使用的字符。

目标是将2改成3,以便用replacement替换3个地方,通过改3个地方找到所有可能的组合。

很高兴从您的解决方案中学习,谢谢。

让我们先讨论一下您现在正在做什么,然后我们构建一个类似的解决方案。正如您在评论中阐明的那样,您的最终目标是

compute all possible ways you could replace exactly three characters in string with characters in char

外环

你做到了 combinations(tuple(range(len(string))), 2)。因此,首先创建一个包含从 0len(string) 的所有值的元组,然后生成由该元组中的两个值组成的所有可能组合。这里没有必要使用 tuple()。根据 docscombinations 的第二个参数是它应该选择一个值多少次来构建一个结果。同样在文档中,我们可以找到 combinations 不会重用结果元组的值的信息。

所以我们可以修改为

for i, j, k in combinations(range(len(string)), 3)
# generates tuples like this:
# >>> list(combinations(range(4), 3))
# [(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)]

内循环

您从 char 中选择了两个角色。这次,根据 docs 相当于 ((x,y) for x in A for y in B)。请注意,文档显示还有第二个可选参数:

To compute the product of an iterable with itself, specify the number of repetitions with the optional repeat keyword argument. For example, product(A, repeat=4) means the same as product(A, A, A, A).

所以我们可以使用for char1, char2, char3 in product(char, repeat=3)。在下面的例子中可以看到,这次有重复。

list(product([1,2,3,4], repeat=3))
[(1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 1, 4), (1, 2, 1), (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 1), (1, 3, 2), (1, 3, 3), (1, 3, 4), (1, 4, 1), (1, 4, 2), (1, 4, 3), (1, 4, 4), (2, 1, 1), (2, 1, 2), (2, 1, 3), (2, 1, 4), (2, 2, 1), (2, 2, 2), (2, 2, 3), (2, 2, 4), (2, 3, 1), (2, 3, 2), (2, 3, 3), (2, 3, 4), (2, 4, 1), (2, 4, 2), (2, 4, 3), (2, 4, 4), (3, 1, 1), (3, 1, 2), (3, 1, 3), (3, 1, 4), (3, 2, 1), (3, 2, 2), (3, 2, 3), (3, 2, 4), (3, 3, 1), (3, 3, 2), (3, 3, 3), (3, 3, 4), (3, 4, 1), (3, 4, 2), (3, 4, 3), (3, 4, 4), (4, 1, 1), (4, 1, 2), (4, 1, 3), (4, 1, 4), (4, 2, 1), (4, 2, 2), (4, 2, 3), (4, 2, 4), (4, 3, 1), (4, 3, 2), (4, 3, 3), (4, 3, 4), (4, 4, 1), (4, 4, 2), (4, 4, 3), (4, 4, 4)]

循环内容

你最后在这里做的是打印 string 除了你想要替换字符的位置。您使用内循环中的字符和外循环中的位置。如此有效,对于每两个字符(包括重复字符),您会为每一种可能的定位方式打印一个字符串(没有重复,因为您不能将它们放在同一位置)。

由于我们现在已经修改了循环生成三个位置和三个字符,我们只需要添加第三个修改。

看来我们很幸运:combinations 仅按升序生成位置元组。所以我们可以假设 i < j < k.

print(string[:i] + char1 + string[i+1:j] + char2 + string[j+1:k] + char3 + string[k+1:])

把它们放在一起

# same as before
from itertools import combinations, product
string = "abcd012345"
char = "01268abc"

# modified as explained above
for i, j, k in combinations(range(len(string)), 3):
  for char1, char2, char3 in product(char, repeat=3):
    print(string[:i] + char1 + string[i+1:j] + char2 + string[j+1:k] + char3 + string[k+1:])

这将打印数千个字符串。您可能还需要考虑您是在寻找不同的输出字符串还是只是原始组合:

该解决方案只是您的 2 字符方法的概括,其中固定大小的逻辑根据参数可变。

from itertools import combinations,product

def replaceCombo(string,char,count):
    for positions in combinations(range(len(string)),count):
        for characters in product(char,repeat=count):
            newString=list(string)
            for p,c in zip(positions,characters):
                newString[p]=c
            yield "".join(newString)


string = "abcd012345"
char   = "01268abc"
for newString in replaceCombo(string,char,2): print(newString)

00cd012345
01cd012345
02cd012345
06cd012345
... total 2,880 strings

print(len(set(replaceCombo(string,char,2)))) # 2,538 distinct strings

for newString in replaceCombo(string,char,3): print(newString)
000d012345
001d012345
002d012345
006d012345
008d012345
00ad012345
... total 61,440 strings

print(len(set(replaceCombo(string,char,3)))) # 51,094 distinct strings