Find the nth occurrence of substring in a string Find the nth occurrence of substring in a string python python

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:

  1. Simple is better than complex.
  2. Flat is better than nested.
  3. 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)