简体   繁体   English

使用 itertools 排列和乘积返回所有可能的字符排序

[英]Using itertools permutations and product to return all possible character orderings

I am having a bit of difficulty merging itertools permutations and product to get the output (list) I desire.我在合并 itertools 排列和乘积以获得我想要的 output(列表)时遇到了一些困难。 I am trying to generate all orderings of characters with consideration for wildcard chars (?, *).我试图在考虑通配符字符(?,*)的情况下生成所有字符顺序。

For instance, if input is A?, I am trying to get the following output: AA AB BA AC CA AD DA... etc例如,如果输入是 A?,我试图获得以下 output:AA AB BA AC CA AD DA...等

The code below does a great job of generating all permutations, with the wildcards left in.下面的代码很好地生成了所有排列,并保留了通配符。

chars = "HELLO?"
for i in range(len(chars)+1):
    perms = map(''.join, permutations(chars,i))
    for perm in perms:
        print(perm)

And this code allows me to substitute wildcard chars with all 26 possible alphabetic characters.这段代码允许我用所有 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)

What is the best way to combine these two segments (most efficient) to get the output I am looking for?将这两个部分组合起来(最有效)以获得我正在寻找的 output 的最佳方法是什么? Is there a better, more efficient way to do this?有没有更好、更有效的方法来做到这一点?

You can just nest your two for loops, Append the values to a list if you want;如果需要,您可以将两个for循环 Append 值嵌套到列表中; but it will be big: if memory is a concern and you only need the values once I'd use a generator:但它会很大:如果 memory 是一个问题,你只需要在我使用生成器后使用这些值:

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)

The duplicates you mention in comments are because the outputs of itertools.product which are separately permuted share 5/6 of their letters.您在评论中提到的重复项是因为itertools.product的输出分别排列了 5/6 的字母。 This code replaces product (recursively to handle multiple wilds) and eliminates duplicates:此代码替换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)

In python 3, using yield from would simplify a bit.在 python 3 中,使用yield from会简化一点。

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

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