【问题标题】:Find all substrings in a string in python 3 with brute-force使用蛮力在python 3中查找字符串中的所有子字符串
【发布时间】:2019-03-16 21:07:57
【问题描述】:

我想用蛮力找到L = ['C', 'A', 'B', 'A', 'A', 'X', 'B', 'Y', 'A'] 中的所有子字符串'A' to 'B',这就是我所做的:

def find_substring(L):
    t = 0
    s = []
    for i in range(len(L) - 1):
        l = []
        if ord(L[i]) == 65:
            for j in range(i, len(L)):
                l.append(L[j])
                if ord(L[j]) == 66:
                    t = t + 1
                    s.append(l)
    return s, t

现在我想要输出:

[['A','B'], ['A','B','A','A','X','B'], ['A','A','X','B'], ['A','X','B']]

但我明白了:

[['A','B','A','A','X','B','Y','A'],['A','B','A','A','X','B','Y','A'],['A','A','X','B','Y','A'],['A','X','B','Y','A']]

谁能告诉我我做错了什么?

【问题讨论】:

  • 当你找到一个'B'你需要break退出内循环。
  • @JohnnyMopp 不,因为你想要所有这些。
  • @JoeIddon 好的,我现在明白了。
  • @JohnnyMopp 看看我的回答:)

标签: python string python-3.x substring brute-force


【解决方案1】:

另一种稍微不同的方法是:

L = ['C', 'A', 'B', 'A', 'A', 'X', 'B', 'Y', 'A']

def find_substring(L):
    output = []
    # Start searching for A.
    for i in range(len(L)):
        # If you found one start searching all B's until you reach the end.
        if L[i]=='A':
            for j in range(i,len(L),1):
                # If you found a B, append the sublist from i index to j+1 index (positions of A and B respectively).
                if L[j]=='B':
                    output.append(L[i:j+1])
    return output

result = find_substring(L)
print(result)

输出:

[['A', 'B'], ['A', 'B', 'A', 'A', 'X', 'B'], ['A', 'A', 'X', 'B'], ['A', 'X', 'B']]

如果您需要对上述内容的列表理解:

def find_substring(L):
    output = [L[i:j+1] for i in range(len(L)) for j in range(i,len(L),1) if L[i]=='A' and L[j]=='B']
    return output

【讨论】:

    【解决方案2】:

    那么,您想要所有以“A”开头并以“B”结尾的子字符串吗?

    当您使用@Joeidden 的代码时,您可以将需要的for i in range(len(L) - 1): 更改为for i in range(len(L)):,因为只有以“B”结尾的字符串才会附加到s

    def find_substring(L):
        s = []
        for i in range(len(L)):
            l = []
            if L[i] == 'A':
                for j in range(i, len(L)):
                    l.append(L[j])
                    if L[j] == 'B':
                        s.append(l[:])
    return s
    

    【讨论】:

      【解决方案3】:

      您可以将 l 重置为字符串的副本,将 l 附加到最后一个附加之后的 l = l[:] 之后。

      【讨论】:

        【解决方案4】:

        最好先找到'A''B' 的所有索引,然后遍历它们,避免暴力破解。

        def find_substrings(lst)
            idx_A = [i for i, c in enumerate(lst) if c == 'A']
            idx_B = [i for i, c in enumerate(lst) if c == 'B']
        
            return [lst[i:j+1] for i in idx_A for j in idx_B if j > i]
        

        【讨论】:

        • 为什么不一次性构建idx_Aidx_B
        • 非常类似于我作为对另一个答案的评论发布的内容...您可以将enumerate(lst, 1) 用于idx_B,然后避免使用j+1...
        【解决方案5】:

        当您将l 附加到s 时,您将引用 添加到列表中,然后您会继续增长。您想在追加时追加l 列表内容的副本,以使其保持静态。

                   s.append(l[:])
        

        这是一个常见的常见问题解答;这个问题可能应该作为重复关闭。

        【讨论】:

        【解决方案6】:

        问题在于列表s 包含对l 列表的引用。

        因此,即使您将正确的 l 列表附加到 s,它们在被附加后也会更改,因为 j 循环的未来迭代会修改 l 列表。

        您可以通过附加l 列表的副本来解决此问题:l[:]

        另外,您可以直接比较字符串,无需转换为ASCII。

        def find_substring(L):
            s = []
            for i in range(len(L) - 1):
                l = []
                if L[i] == 'A':
                    for j in range(i, len(L)):
                        l.append(L[j])
                        if L[j] == 'B':
                            s.append(l[:])
            return s
        

        现在有效:

        >>> find_substring(['C', 'A', 'B', 'A', 'A', 'X', 'B', 'Y', 'A'])
        [['A', 'B'], ['A', 'B', 'A', 'A', 'X', 'B'], ['A', 'A', 'X', 'B'], ['A', 'X', 'B']]
        

        【讨论】:

        • 还可以使用带有预先计算的开始/结束索引的列表组合,然后切片,例如:[L[a:b] for a in (idx for idx, v in enumerate(L) if v == 'A') for b in (idx for idx, v in enumerate(L, 1) if v == 'B') if a < b]
        猜你喜欢
        • 2016-05-24
        • 2021-08-13
        • 1970-01-01
        • 1970-01-01
        • 2019-03-29
        • 1970-01-01
        • 2017-08-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多