在字符串中找到第n个子串出现位置
这看起来应该很简单,但我刚学Python,想用最符合Python风格的方法来做。
我想找到一个字符串中某个子字符串出现的第n次的位置。
应该有类似我想做的事情的办法,就是
mystring.find("substring", 2nd)
在Python中怎么实现这个呢?
27 个回答
52
这段代码会找到字符串中第二次出现的子字符串。
def find_2nd(string, substring):
return string.find(substring, string.find(substring) + 1)
补充:我没有仔细考虑性能问题,不过快速的递归方法可以帮助找到第n次出现的情况:
def find_nth(string, substring, n):
if (n == 1):
return string.find(substring)
else:
return string.find(substring, find_nth(string, substring, n - 1) + 1)
128
这里有一个更符合Python风格的简单迭代解决方案:
def find_nth(haystack: str, needle: str, n: int) -> int:
start = haystack.find(needle)
while start >= 0 and n > 1:
start = haystack.find(needle, start+len(needle))
n -= 1
return start
示例:
>>> find_nth("foofoofoofoo", "foofoo", 2)
6
如果你想找到第n个重叠的needle
出现,可以每次增加1
,而不是增加len(needle)
,像这样:
def find_nth_overlapping(haystack, needle, n):
start = haystack.find(needle)
while start >= 0 and n > 1:
start = haystack.find(needle, start+1)
n -= 1
return start
示例:
>>> find_nth_overlapping("foofoofoofoo", "foofoo", 2)
3
这个方法比Mark的版本更容易理解,而且不需要像分割版本那样额外占用内存,也不需要导入正则表达式模块。它还遵循了Python的一些原则,和各种re
方法相比更符合这些原则:
- 简单胜于复杂。
- 扁平胜于嵌套。
- 可读性很重要。
93
我觉得马克的迭代方法是比较常见的做法。
这里有一种用字符串分割的替代方法,这种方法在处理查找相关的过程时通常很有用:
def findnth(haystack, needle, n):
parts= haystack.split(needle, n+1)
if len(parts)<=n+1:
return -1
return len(haystack)-len(parts[-1])-len(needle)
还有一个快速的方法(虽然有点不太干净,因为你需要选择一些无法匹配目标的杂项):
'foo bar bar bar'.replace('bar', 'XXX', 1).find('bar')