1

I want to count the number of occurrences of the substring "bob" within the string s. I do this exercise for an edX Course.

s = 'azcbobobegghakl'
counter = 0
numofiterations = len(s)
position = 0

#loop that goes through the string char by char
for iteration in range(numofiterations):
    if s[position] == "b":                  # search  pos. for starting point
        if s[position+1:position+2] == "ob":    # check if complete
            counter += 1        
    position +=1

print("Number of times bob occurs is: " + str(counter))

However it seems that the s[position+1:position+2] statement is not working properly. How do i adress the two chars behind a "b"?

Ajaybee
  • 25
  • 2
  • Possible duplicate of [string count with overlapping occurrences](https://stackoverflow.com/questions/2970520/string-count-with-overlapping-occurrences) – Chris_Rands Oct 16 '17 at 20:25

3 Answers3

1

The second slice index isn't included. It means that s[position+1:position+2] is a single character at position position + 1, and this substring cannot be equal to ob. See a related answer. You need [:position + 3]:

s = 'azcbobobegghakl'
counter = 0
numofiterations = len(s)
position = 0

#loop that goes through the string char by char
for iteration in range(numofiterations - 2):
    if s[position] == "b":                  # search  pos. for starting point
        if s[position+1:position+3] == "ob":    # check if complete
            counter += 1        
    position +=1

print("Number of times bob occurs is: " + str(counter))
# 2
Eric Duminil
  • 52,989
  • 9
  • 71
  • 124
  • I would also check if position+3 is inside the string... or reducing the range by 2 to be sure that the check will be always valid – Roberto Trani Oct 16 '17 at 20:25
  • @RobertoTrani: `position + 3` is allowed to be larger than `len(s)` without raising an error. I could change the `range` though, yes. – Eric Duminil Oct 16 '17 at 20:28
  • Is this necessary? I just added a b in the end for testing this and worked fine. From my understanding, it would simply compare "ob" with an empty string? – Ajaybee Oct 16 '17 at 20:40
  • @Ajaybee: Exactly. So no, it's not necessary, but if `position` is equal to `len(s) - 2`, you know it cannot match anymore. – Eric Duminil Oct 16 '17 at 20:42
0

You could use .find with an index:

s = 'azcbobobegghakl'

needle = 'bob'

idx = -1; cnt = 0
while True:
    idx = s.find(needle, idx+1)
    if idx >= 0:
        cnt += 1
    else:
        break

print("{} was found {} times.".format(needle, cnt))
# bob was found 2 times.
Jan
  • 42,290
  • 8
  • 54
  • 79
0

Eric's answer explains perfectly why your approach didn't work (slicing in Python is end-exclusive), but let me propose another option:

s = 'azcbobobegghakl'
substrings = [s[i:] for i in range(0, len(s))]
filtered_s = filter(substrings, lambda s: s.startswith("bob"))
result = len(filtered_s)

or simply

s = 'azcbobobegghakl'
result = sum(1 for ss in [s[i:] for i in range(0, len(s))] if ss.startswith("bob"))
Adam Smith
  • 52,157
  • 12
  • 73
  • 112