Find the nth occurrence of substring in a string
Here's a more Pythonic version of the straightforward iterative solution:
def find_nth(haystack, needle, n): start = haystack.find(needle) while start >= 0 and n > 1: start = haystack.find(needle, start+len(needle)) n -= 1 return start
Example:
>>> find_nth("foofoofoofoo", "foofoo", 2)6
If you want to find the nth overlapping occurrence of needle
, you can increment by 1
instead of len(needle)
, like this:
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
Example:
>>> find_nth_overlapping("foofoofoofoo", "foofoo", 2)3
This is easier to read than Mark's version, and it doesn't require the extra memory of the splitting version or importing regular expression module. It also adheres to a few of the rules in the Zen of python, unlike the various re
approaches:
- Simple is better than complex.
- Flat is better than nested.
- Readability counts.
Mark's iterative approach would be the usual way, I think.
Here's an alternative with string-splitting, which can often be useful for finding-related processes:
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)
And here's a quick (and somewhat dirty, in that you have to choose some chaff that can't match the needle) one-liner:
'foo bar bar bar'.replace('bar', 'XXX', 1).find('bar')
This will find the second occurrence of substring in string.
def find_2nd(string, substring): return string.find(substring, string.find(substring) + 1)
Edit: I haven't thought much about the performance, but a quick recursion can help with finding the nth occurrence:
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)