That's how index()
is designed; to only return the first occurrence.
If you want to find all occurrences, you must call it multiple times in a loop or with recursion. Before we do that, you should know that you can provide start
and end
parameters to define where to search in the sentence:
>>> "cat cat".index("cat")
0
>>> "cat cat".index("cat", 1) # start search from index 1
4
>>> "cat cat".index("cat", 1, 4) # ...and stop search right before index 4
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: substring not found
This way we can avoid getting the same index all the time in our loop:
s = "cat cat"
indexes = []
index = -1
while True:
try:
index = s.index("cat", index + 1)
except ValueError:
break
indexes.append(index)
print(indexes)
# Output: [0, 4]
Here's a recursive generator if you want to go fancy:
def find_indices(s, sub, start=0, end=None):
if end is None:
end = len(s)
try:
start = s.index(sub, start, end)
except ValueError:
return
yield start
yield from find_all_indexes(s, sub, start + 1, end)
Usage (also still supports start
and end
arguments):
>>> list(find_indices("cat cat cat cat", "cat"))
[0, 4, 8, 12]
Or if you want a non-recursive generator, you could use the original while
loop and have it yield
instead of append to a list:
def find_indices(s, sub, start=0, end=None):
if end is None:
end = len(s)
start -= 1
while True:
try:
start = s.index(sub, start + 1, end)
except ValueError:
break
yield start
Exact same usage as before.