【问题标题】:How to find all possible permutation of two strings within constant length如何在恒定长度内找到两个字符串的所有可能排列
【发布时间】:2020-11-09 18:04:23
【问题描述】:

我想在恒定长度(5) 内找到两个字符串列表的所有可能排列。假设list_1 = ["A"]list_2 = ["BB"]

所有可能的组合是:

A A A A A
A A A BB
A A BB A
A BB A A
BB A A A
A BB BB
BB A BB
BB BB A

我试图用下面的代码来实现它,但我不确定如何为它定义长度 5。

import itertools 
from itertools import permutations 

list_1 = ["A"] 
list_2 = ["BB"] 
unique_combinations = [] 

permut = itertools.permutations(list_1, 5) 

for comb in permut: 
    zipped = zip(comb, list_2) 
    unique_combinations.append(list(zipped)) 

print(unique_combinations) 

【问题讨论】:

    标签: python string combinations permutation itertools


    【解决方案1】:

    使用递归:

    list_1 = ["A"]
    list_2 = ["BB"]
    size = 5
    
    strs = list_1 + list_2
    res = []
    
    def helper(strs, size, cur, res):
        if size == 0:
            res.append(cur)
            return
        if size < 0:
            return
    
        for s in strs:
            helper(strs, size-len(s), cur+[s], res)
    
    helper(strs, size, [], res)
    print(res)
    

    没有递归:

    list_1 = ["A"]
    list_2 = ["BB"]
    size = 5
    
    strs = list_1 + list_2
    res = []
    
    q = [[]]
    while q:
        t = q.pop()
        for s in strs:
            cur = t + [s]
            cursize = len(''.join(cur))
            if cursize == size:
                res.append(cur)
            elif cursize < size:
                q.append(cur)
    print(res)
    

    【讨论】:

    • 通常我会避免像排列这样的递归。您可能会遇到更多征税输入的递归限制。我会尝试用一个while循环来重构它。
    【解决方案2】:

    您可以执行以下操作:

    import itertools
    
    unique_combinations = []
    
    permut = itertools.product(["A","B"], repeat=5)
    for comb in permut:
        l = "".join(comb)
        c_bb = l.count("BB")
        c_a = l.count("A")
        if 2*c_bb + c_a == 5:
            unique_combinations.append(l)
    print(unique_combinations)
    

    这将给出:

    ['AAAAA', 'AAABB', 'AABBA', 'ABBAA', 'ABBBB', 'BBAAA', 'BBABB', 'BBBBA']
    

    首先找到所有长度为 5 的类字符串由 5 个元素组成,“A”或“B”。然后使用string.count 计算您感兴趣的每个子字符串的出现次数,如果相等,则保存它。

    【讨论】:

    • 这种情况只适用于一组非常严格的输入。如果输入是['A', 'BC'],那么这将失败。我会搜索更一般的东西。
    • @flakes 我同意,但是你只需要调整传递给产品的值并调整条件,我认为这是一个简单的改变,可以是普遍的。你不同意吗?
    • 我认为一般情况下会有很多变化。考虑choices=['A', 'BC', 'C'] 的情况,或者任何输入在该方法之前未知的情况。假设您提供def perm_with_size(choices, limit):。想想如何支持这些未知数。
    【解决方案3】:

    您可以使用itertools.product 查找'A''BB' 的所有可能组合(repeat 从 3 到 5,因为这些是可接受答案中的元素数量),然后过滤比基于它们的总长度为 5 个字符:

    import itertools
    
    all_options = []
    for i in range(3,6):
        all_options += list(itertools.product(['A', 'BB'], repeat=i))
    all_options = [i for i in all_options if len(''.join(i)) == 5]
    print(all_options)
    

    输出:

    [('A', 'BB', 'BB'), ('BB', 'A', 'BB'), ('BB', 'BB', 'A'), ('A', 'A', 'A', 'BB'), ('A', 'A', 'BB', 'A'), ('A', 'BB', 'A', 'A'), ('BB', 'A', 'A', 'A'), ('A', 'A', 'A', 'A', 'A')]
    

    【讨论】:

    • 我可能会建议使用set 而不是list 来代替all_options
    【解决方案4】:

    你需要一个这样的递归函数:

    def f(words, N, current = ""):
        if(len(current)<N):
            for i in words:
                f(words, N, current+i)
        elif(len(current)==N):
            print(current)
            
    
    f(["A", "BB"], 5)
    

    编辑:不幸的是,如果列表中的两个或多个单词共享同一个字母,则此函数会返回重复项。所以正确的做法应该是把所有的return填满一个list,然后去掉重复的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-07
      • 2015-06-18
      • 2019-05-10
      • 2018-08-22
      • 1970-01-01
      相关资源
      最近更新 更多