如何利用Python列出字符串中模式的所有出现次数

265 阅读3分钟

哪种方法可以找到模式在给定字符串中的所有出现的列表?

问题的提出

问题的提出:给定一个长字符串和一个短字符串。如何找到短字符串在长字符串中的所有出现?

请看下面的例子。

  • 较长的字符串'Finxters learn Python with Finxter'
  • 较短的字符串模式。 'Finxter'
  • 结果1:['Finxter', 'Finxter']

作为选择,你可能还想得到短字符串在长字符串中出现的位置。

  • 结果2[(0, 'Finxter'), (27, 'Finxter')]

方法1:Regex re.finditer()

要获得一个模式在给定字符串中的所有出现,你可以使用正则表达式方法 [re.finditer(pattern, string)](https://blog.finxter.com/python-regex-finditer/ "Python Regex Finditer()").其结果是一个匹配对象的迭代器--你可以使用match.start()match.end() 函数检索匹配的索引。

import re
s = 'Finxters learn Python with Finxter'
pattern = 'Finxter'

# Method 1: re.finditer
for m in re.finditer(pattern, s):
    print(pattern, 'matched from position', m.start(), 'to', m.end())

输出结果是:

Finxter matched from position 0 to 7
Finxter matched from position 27 to 34

方法2:re.finditer() + 列表理解

为了将匹配的模式字符串、开始索引和结束索引变成一个图元的列表,你可以使用以下基于列表理解单行代码

[(pattern, m.start(), m.end()) for m in re.finditer(pattern, s)].

import re
s = 'Finxters learn Python with Finxter'
pattern = 'Finxter'

# Method 2: re.finditer + list comprehension
l = [(pattern, m.start(), m.end()) for m in re.finditer(pattern, s)]
print(l)

其输出结果是:

[('Finxter', 0, 7), ('Finxter', 27, 34)]

方法3:Python字符串 startswith()

Pythonstartswith(prefix, start) 方法在开始搜索索引prefix 时,检查给定的字符串是否以前缀开始start

我们可以在一个列表理解语句中使用startswith() 方法,像这样找到一个给定字符串中子串的所有出现(位置)。

[i for i in range(len(s)) if s.startswith(pattern, i)]

下面是使用这种方法的完整例子。

s = 'Finxters learn Python with Finxter'
pattern = 'Finxter'

# Method 4: startswith() to find all occurrences of substring in string
l = [i for i in range(len(s)) if s.startswith(pattern, i)]

print(l)

输出显示了在原始字符串中发现子串(模式)的起始索引列表

[0, 27]

方法4:re.findall()

如果你只对给定字符串中没有索引位置的匹配子串感兴趣,你可以使用以下方法。

要找到给定字符串中的所有子串,可以使用re.findall(substring, string) ,该函数返回一个匹配子串的列表--每个匹配子串。

import re
s = 'Finxters learn Python with Finxter'
pattern = 'Finxter'

# Method 4: re.findall() to find all patterns in string
l = re.findall(pattern, s)
print(l)
# ['Finxter', 'Finxter']

如果你想知道regex.findall() 方法是如何工作的,可以看一下这个图形。

方法5:无REGEX,递归,重叠

下面这个方法是基于递归的,它不需要任何外部库。

我们的想法是反复寻找字符串中下一个出现的子串模式,并在一个较短的字符串上递归调用相同的方法--将起始位置向右移动,直到再也找不到匹配的字符串。

当你通过递归调用时,所有找到的子串匹配都累积在一个变量中acc

s = 'Finxters learn Python with Finxter'
pattern = 'Finxter'

# Method 5: recursive, without regex
def find_all(pattern, # string pattern
             string, # string to be searched
             start=0, # ignore everything before start
             acc=[]): # All occurrences of string pattern in string

    # Find next occurrence of pattern in string
    i = string.find(pattern, start)
    
    if i == -1:
        # Pattern not found in remaining string
        return acc
    
    return find_all(pattern, string, start = i+1,
                    acc = acc + [(pattern, i)]) # Pass new list with found pattern

l = find_all(pattern, s)
print(l)

输出结果是。

[('Finxter', 0), ('Finxter', 27)]

请注意,这个方法也可以找到重叠的匹配--与消耗所有部分匹配的子串的regex方法不同。