Using timeit
to time the function running over 1000 iterations, as follows:
import timeit
def search(word=None,source=None):
word = "is"
source = "Lorem Ipsum is simply dummy text"
places = []
for x in range(0, len(source)):
if source[x] == word[0]:
if source[x:x + len(word)] == word:
places.append(x)
return places
print timeit.timeit(search, number=1000)
This code gives us the following results (over 4 runs):
0.259000062943
0.12299990654
0.174999952316
0.0520000457764
So, we'll use that as our baseline for improvement (further runs stay constant around .052/1000).
Let's grab the low hanging fruit - caching the len
calls:
import timeit
def search(word=None,source=None):
word = "is"
source = "Lorem Ipsum is simply dummy text"
places = []
len_word = len(word)
len_source = len(source)
for x in range(0, len_source):
if source[x] == word[0]:
if source[x:x + len_word] == word:
places.append(x)
return places
print timeit.timeit(search, number=1000)
Improvement:
0.0519998493195
0.047000169754
0.0499999523163
0.0490000247955
Now, what happens if we get rid of places
and just return once we find the string, as follows:
import timeit
def search(word=None,source=None):
word = "is"
source = "Lorem Ipsum is simply dummy text"
len_word = len(word)
len_source = len(source)
for x in range(0, len_source):
if source[x] == word[0]:
if source[x:x + len_word] == word:
return x
print timeit.timeit(search, number=1000)
Well, this happened:
0.0349998474121
0.0299999713898
0.0279998779297
0.0279998779297
Nice! But wait, there's more! We can just use Python built ins:
import timeit
def search(word=None,source=None):
word = "is"
source = "Lorem Ipsum is simply dummy text"
return source.lower().find(word.lower())
print timeit.timeit(search, number=1000)
to halve the time it took us with the brute force approach:
0.0140001773834
0.0149999599457
0.0120000839233
0.0110000114441
These are the two final products, one brute force, and one using built ins, and both return the same int
value when a word is found:
def search(word,source):
len_word = len(word)
len_source = len(source)
for x in range(0, len_source):
if source[x] == word[0]:
if source[x:x + len_word] == word:
return x
def search(word,source):
return source.lower().find(word.lower())
::EDIT::
In regards to the comment (not same as OPs code), turn the function into an iterator rather than returning a list. This will give you the speed boost of the prior code, and still give you all the places of occurrence:
def search(word,source):
len_word = len(word)
len_source = len(source)
for x in range(0, len_source):
if source[x] == word[0]:
if source[x:x + len_word] == word:
yield x
for occurrence in search():
print occurrence
EDIT:::
Getting rid of if source[x] == word[0]
also gives us a nice speedup:
def search(word,source):
len_word = len(word)
len_source = len(source)
for x in range(0, len_source):
if source[x:x + len_word] == word:
yield x
EDIT:::
Another quick win, caching the first chars:
def search(word,source):
places = []
len_word = len(word)
len_source = len(source)
first_char = word[0]
for x in range(0, len_source):
if source[x] == first_char:
if source[x:x + len_word] == word:
places.append(x)
return places