使用 itertools 排列和乘积 return 所有可能的字符排序
Using itertools permutations and product to return all possible character orderings
我在合并 itertools 排列和乘积以获得我想要的输出(列表)时遇到了一些困难。我正在尝试在考虑通配符字符 (?, *) 的情况下生成所有字符顺序。
例如,如果输入是 A?,我试图获得以下输出:
AA
AB
学士
空调
加州
广告
DA ...等
下面的代码很好地生成了所有排列,其中保留了通配符。
chars = "HELLO?"
for i in range(len(chars)+1):
perms = map(''.join, permutations(chars,i))
for perm in perms:
print(perm)
这段代码允许我用所有 26 个可能的字母字符替换通配符。
chars = "HELLO?"
wilds = [('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z') if char == "?" else (char) for char in chars]
for p in itertools.product(*wilds):
print(p)
将这两个部分组合起来(最有效)以获得我正在寻找的输出的最佳方法是什么?有没有更好、更有效的方法来做到这一点?
您可以只嵌套两个 for
循环!如果需要,可以将值附加到列表中,但它会很大;如果内存是一个问题并且你只需要在我使用生成器后的值:
import itertools
def perm_with_wild_generator(chars):
wilds = [('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z') if char == "?" else (char) for char in chars]
for p in itertools.product(*wilds):
for i in range(len(p) + 1):
perms = map(''.join, itertools.permutations(p, i))
for perm in perms:
yield perm
for c in perm_with_wild_generator("HELLO?"):
print(c)
您在评论中提到的重复项是因为 itertools.product
的输出分别排列了 5/6 的字母。此代码替换 product
(递归处理多个百搭)并消除重复项:
import itertools
def replace_wild(chars, wilds):
if '?' not in chars:
yield chars
else:
for wild in wilds:
for w in replace_wild(chars.replace("?", wild, 1), wilds):
yield w
def perm_with_wild_generator(chars):
wilds = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'} - set(chars)
for i in range(len(chars) + 1):
perms = map(''.join, itertools.permutations(chars, i))
for perm in perms:
for w in replace_wild(perm, wilds | set(perm.replace('?', ""))):
yield w
for c in perm_with_wild_generator("HELLO?"):
print(c)
在 python 3 中,使用 yield from
会简化一些。
我在合并 itertools 排列和乘积以获得我想要的输出(列表)时遇到了一些困难。我正在尝试在考虑通配符字符 (?, *) 的情况下生成所有字符顺序。
例如,如果输入是 A?,我试图获得以下输出: AA AB 学士 空调 加州 广告 DA ...等
下面的代码很好地生成了所有排列,其中保留了通配符。
chars = "HELLO?"
for i in range(len(chars)+1):
perms = map(''.join, permutations(chars,i))
for perm in perms:
print(perm)
这段代码允许我用所有 26 个可能的字母字符替换通配符。
chars = "HELLO?"
wilds = [('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z') if char == "?" else (char) for char in chars]
for p in itertools.product(*wilds):
print(p)
将这两个部分组合起来(最有效)以获得我正在寻找的输出的最佳方法是什么?有没有更好、更有效的方法来做到这一点?
您可以只嵌套两个 for
循环!如果需要,可以将值附加到列表中,但它会很大;如果内存是一个问题并且你只需要在我使用生成器后的值:
import itertools
def perm_with_wild_generator(chars):
wilds = [('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z') if char == "?" else (char) for char in chars]
for p in itertools.product(*wilds):
for i in range(len(p) + 1):
perms = map(''.join, itertools.permutations(p, i))
for perm in perms:
yield perm
for c in perm_with_wild_generator("HELLO?"):
print(c)
您在评论中提到的重复项是因为 itertools.product
的输出分别排列了 5/6 的字母。此代码替换 product
(递归处理多个百搭)并消除重复项:
import itertools
def replace_wild(chars, wilds):
if '?' not in chars:
yield chars
else:
for wild in wilds:
for w in replace_wild(chars.replace("?", wild, 1), wilds):
yield w
def perm_with_wild_generator(chars):
wilds = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'} - set(chars)
for i in range(len(chars) + 1):
perms = map(''.join, itertools.permutations(chars, i))
for perm in perms:
for w in replace_wild(perm, wilds | set(perm.replace('?', ""))):
yield w
for c in perm_with_wild_generator("HELLO?"):
print(c)
在 python 3 中,使用 yield from
会简化一些。