【问题标题】:Using itertools permutations and product to return all possible character orderings使用 itertools 排列和产品返回所有可能的字符顺序
【发布时间】:2021-02-17 19:03:48
【问题描述】:

我在合并 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)

结合这两个部分(最有效)以获得我正在寻找的输出的最佳方法是什么?有没有更好、更有效的方法来做到这一点?

【问题讨论】:

    标签: python product permutation itertools


    【解决方案1】:

    您可以嵌套两个 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)
    

    您在 cmets 中提到的重复项是因为 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 会简化一点。

    【讨论】:

    • 我遇到的问题之一是在您上面的代码中出现。如果你运行它,它会在一个循环中打印出所有排列,并且每个排列有 26 个副本。如果我为“HELLO”运行它?它运行了很长时间。甚至用“他?”来运行这个。需要一段时间。这也让我认为排列列表可以以更有效的方式构建。也许使用集合或字典来清除多余的烫发?
    • 这很奇怪。这个确切的代码对我来说在 0.0005 秒内运行,并且每个排列只打印 2 个(因为 2 'L's in hello)。你确定你使用的是itertools.permutation
    • 是的,我可以复制并粘贴上面的块,它运行大约 5 分钟,遍历 perm_with_wild_generator 打印语句 26 次。
    • 我刚刚更新了它以修复一个丢失的案例——现在有一些重复但比 26 少很多
    猜你喜欢
    • 1970-01-01
    • 2015-02-09
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 2018-11-07
    • 2020-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多