Dewey Banks
Dewey Banks

Reputation: 323

Number of occurrences of a substring in a string

I need to count the nunber of times the substring 'bob' occurs in a string.

Example problem: Find the number of times 'bob' occurs in string s such that

"s = xyzbobxyzbobxyzbob"  #(here there are three occurrences)

Here is my code:

s = "xyzbobxyzbobxyzbob"

numBobs = 0

while(s.find('bob') >= 0)
   numBobs = numBobs + 1
   print numBobs

Since the find function in Python is supposed to return -1 if a substring is unfound the while loop ought to end after printing out the incremented number of bobs each time it finds the substring.

However the program turns out to be an infinite loop when I run it.

Upvotes: 2

Views: 7406

Answers (6)

Lalit Jangid
Lalit Jangid

Reputation: 1

def count_substring(string, sub_string):
count=a=0
while True:
    a=string.find(sub_string)
    string=string[a+1:]
    if a>=0:
        count=count+1;
    else:
        break
return count

Upvotes: 0

RMC
RMC

Reputation: 1

Here you have an easy function for the task:

def countBob(s):
number=0
while s.find('Bob')>0:
    s=s.replace('Bob','',1)
    number=number+1        
return number

Then, you ask countBob whenever you need it:

countBob('This Bob runs faster than the other Bob dude!')

Upvotes: 0

Sam Slotnick
Sam Slotnick

Reputation: 1

Here is a solution that returns number of overlapping sub-strings without using Regex: (Note: the 'while' loop here is written presuming you are looking for a 3-character sub-string i.e. 'bob')

bobs = 0
start = 0
end = 3
while end <= len(s) + 1 and start < len(s)-2 :
    if s.count('bob', start,end) == 1:
        bobs += 1
    start += 1
    end += 1

print(bobs)

Upvotes: 0

Anurag Uniyal
Anurag Uniyal

Reputation: 88737

When you do s.find('bob') you search from the beginning, so you end-up finding the same bob again and again, you need to change your search position to end of the bob you found.

string.find takes start argument which you can pass to tell it from where to start searching, string.find also return the position are which it found bob, so you can use that, add length of bob to it and pass it to next s.find.

So at start of loop set start=0 as you want to search from start, inside loop if find returns a non-negative number you should add length of search string to it to get new start:

srch = 'bob'
start = numBobs = 0 while start >= 0:
    pos = s.find(srch, start)
    if pos < 0:
      break
    numBobs += 1
    start = pos + len(srch)

Here I am assuming that overlapped search string are not considered

Upvotes: 2

user2555451
user2555451

Reputation:

For this job, str.find isn't very efficient. Instead, str.count should be what you use:

>>> s = 'xyzbobxyzbobxyzbob'
>>> s.count('bob')
3
>>> s.count('xy')
3
>>> s.count('bobxyz')
2
>>>

Or, if you want to get overlapping occurrences, you can use Regex:

>>> from re import findall
>>> s = 'bobobob'
>>> len(findall('(?=bob)', s))
3
>>> s = "bobob"
>>> len(findall('(?=bob)', s))
2
>>>

Upvotes: 10

John Kugelman
John Kugelman

Reputation: 361565

find doesn't remember where the previous match was and start from there, not unless you tell it to. You need to keep track of the match location and pass in the optional start parameter. If you don't find will just find the first bob over and over.

find(...)
    S.find(sub [,start [,end]]) -> int

    Return the lowest index in S where substring sub is found,
    such that sub is contained within s[start:end].  Optional
    arguments start and end are interpreted as in slice notation.

    Return -1 on failure.

Upvotes: 0

Related Questions