在另一个字符串中多次查找字符串-Python

在另一个字符串中多次查找字符串-Python,python,string,python-3.x,Python,String,Python 3.x,我正在尝试使用Python的预定义函数(如find和index)查看一个字符串是否存在于另一个字符串中 现在,我的函数使用两个字符串作为参数,一个是我们要搜索的字符串,另一个字符串是我们在第一个字符串中要查找的字符串 如果第一个字符串中存在第二个字符串,我希望我的函数返回它在第一个字符串中出现的所有位置 现在,我的函数能够找到第一个匹配项并返回索引,但是我希望找到多个匹配项,而不仅仅是第一个 下面是我的代码: def multi_find (s, r): s_len = len(s)

我正在尝试使用Python的预定义函数(如find和index)查看一个字符串是否存在于另一个字符串中

现在,我的函数使用两个字符串作为参数,一个是我们要搜索的字符串,另一个字符串是我们在第一个字符串中要查找的字符串

如果第一个字符串中存在第二个字符串,我希望我的函数返回它在第一个字符串中出现的所有位置

现在,我的函数能够找到第一个匹配项并返回索引,但是我希望找到多个匹配项,而不仅仅是第一个

下面是我的代码:

def multi_find (s, r):

    s_len = len(s)
    r_len = len(r)

    if s_len < r_len:
        n = -1
    else:
        m = s_len - r_len
        n = -1  # assume r is not yet found in s
        i = 0

        while n == -1 and i < m:
            # search for r in s until not enough characters are left
            if s[i:i + r_len] == r:
                n = i
            else:
                i = i + 1
    print (n)

multi_find("abcdefabc. asdli! ndsf acba saa abe?", "abc")
def多重查找(s,r):
s_len=len(s)
r_len=len(r)
如果s_len
现在,这将只输出“0”,因为abc首先出现在这里。。如何让它返回“0”和“6”(第二次出现的开始),基本上在找到一个后继续检查

我想创建一个列表,列出所有发生的地方,然后将我添加到该列表中,但当我尝试这样做时,没有任何效果。

您可以:

>>> haystack = "abcdefabc. asdli! ndsf acba saa abe?"
>>> needle = "abc"
>>> for i, _ in enumerate(haystack):
...     if haystack[i:i + len(needle)] == needle:
...         print (i)
...
0
6
def多重查找(s,r):
s_len=len(s)
r_len=len(r)
_完成=[]
如果s_len
使用
regex的另一种选择:

>>> import re
>>> haystack = "abcdefabc. asdli! ndsf acba saa abe?"
>>> needle = "abc"
>>> [m.start() for m in re.finditer(r'{}'.format(re.escape(needle)), haystack)]
[0, 6]
上述解决方案不适用于重叠的子字符串,如
'aaaa'
中有3
'aa'
。因此,如果您也想找到重叠的匹配,那么:

>>> haystack = "bobob"
>>> needle = "bob"
>>> [m.start() for m in re.finditer(r'(?={})'.format(re.escape(needle)), haystack)]
[0, 2]
def多重查找(s,r):
s_len=len(s)
r_len=len(r)
n=[]#假设在s中尚未找到r
如果s_len>=r_len:
m=s_len-r_len
i=0
而我

基本上就是用一个列表替换n,这样您就可以在找到值时继续向其中添加值。您还需要增加i,即使找到匹配项,它也会永远卡在循环中,除非您有while n==-1约束,该约束使它在找到匹配项后立即停止。

最好的方法可能是继续调用find函数(这也是最快的)

输出:

[6, 10]
注意:我认为这个答案仍然是一个很好的“教学答案”,我已经在这个线程的其他地方提交了一个更好的解决方案,没有递归

这允许您通过一个可选的
start
位置,在
s
中开始搜索

这个解决方案是递归的,它可能是最快的实现,也可能不是最快的实现,但它是正确的,我相信它可以让代码很容易地在
s
的每个位置识别三种可能性中的每一种:

  • s
  • 找到另一个
    r
  • 没有找到另一个
    r

  • @雅各布,我希望你会发现这本书很短,但仍然很容易理解

    def multi_find(s, r):
        return [pos for pos in range(len(s)) if s.startswith(r,pos)]
    

    你能给我解释一下enumerate(haystack):'行中“for i”中的“uu”吗?不太清楚这是怎么回事。@jacobmamoliti:这意味着你忽略了存在的变量
    enumerate()
    允许您迭代字符串的位置和字符,但我们不使用字符。因此,我们只对字符串中的每个位置进行迭代。您还可以在enumerate(haystack)中为i,c编写
    以迭代字符串的每个位置
    i
    和每个字符
    c
    (同时)。请注意,“\ux”只是一种惯例,用于向人类读者明确说明-它的作用与使用“x”时没有任何不同我喜欢使用
    re
    ,但由于目标是“返回它在第一个字符串中出现的所有位置”,我认为这没有找到一些有趣的情况,其中
    r
    s
    中多次出现,但其实例重叠。考虑下面的情况:<代码>多个查找(“BOBOB”,“BOB”)< /代码>。使用您的实现,字符串
    “bob”
    肯定出现在
    “bobob”
    中的位置
    2
    ,但它不会返回。我喜欢这一行,但我想我会把它作为一个可能的问题。“这对@Jacob可能没什么关系。”DarrenStone说得很好,他补充了另一个解决方案,同样适用于重叠匹配。
    def multifind(string, value, start = 0, stop = None):
        values = []
        while True:
            found = string.find(value, start, stop)
            if found == -1:
                break
            values.append(found)
            start = found + 1
        return values
    
    print multifind('hello abc abc', 'abc')
    
    [6, 10]
    
    def multi_find(s, r, start=0):
        if start >= len(s): 
            return []
        if s.startswith(r, start):
            return [start] + multi_find(s, r, start+1)
        else:
            return multi_find(s, r, start+1)
    
    def multi_find(s, r):
        return [pos for pos in range(len(s)) if s.startswith(r,pos)]