I\'m trying to see if a string exists in another string with out using Python\'s predefined functions such as find and index..
Right now what my function takes 2 strings
@Jacob, I hope you'll find this one very short yet still easy to understand.
def multi_find(s, r):
return [pos for pos in range(len(s)) if s.startswith(r,pos)]
You can do:
>>> haystack = "abcdefabc. asdli! ndsf acba saa abe?"
>>> needle = "abc"
>>> for i, _ in enumerate(haystack):
... if haystack[i:i + len(needle)] == needle:
... print (i)
...
0
6
Note: I think this answer here is still a good "teaching answer", I have submitted a better solution elsewhere in this thread, without recursion.
def multi_find(s, r, start=0):
if start >= len(s):
return []
if s.startswith(r, start):
return [start] + multi_find(s, r, start+1)
else:
return multi_find(s, r, start+1)
This allows you to pass an optional start
position to begin the search in s
.
This solution is recursive, which may or may not be the fastest implementation, but it is correct and I believe it makes the code easy to identify each of the three possibilities at each position of s
:
s
r
r
def multi_find (s, r):
s_len = len(s)
r_len = len(r)
n = [] # assume r is not yet found in s
if s_len >= r_len:
m = s_len - r_len
i = 0
while i < m:
# search for r in s until not enough characters are left
if s[i:i + r_len] == r:
n.append(i)
i = i + 1
print (n)
multi_find("abcdefabc. asdli! ndsf acba saa abe?", "abc")
Pretty much just replace n with a list so you can keep adding values to it as you find them. You also need to be incrementing i even when a match is found, it would have been stuck in a loop forever except that you had the while n == -1 constraint that made it stop as soon as a match was found.
def multi_find(s, r):
s_len = len(s)
r_len = len(r)
_complete = []
if s_len < r_len:
n = -1
else:
for i in xrange(s_len):
# search for r in s until not enough characters are left
if s[i:i + r_len] == r:
_complete.append(i)
else:
i = i + 1
print(_complete)
multi_find("abcdefabc. asdli! ndsf abc saa abe?", "abc")
Another alternative using regex
:
>>> import re
>>> haystack = "abcdefabc. asdli! ndsf acba saa abe?"
>>> needle = "abc"
>>> [m.start() for m in re.finditer(r'{}'.format(re.escape(needle)), haystack)]
[0, 6]
The above solution will not work for overlapping sub-strings, like there are 3 'aa'
in 'aaaa'
. So, if you want to find overlapping matches as well, then:
>>> haystack = "bobob"
>>> needle = "bob"
>>> [m.start() for m in re.finditer(r'(?={})'.format(re.escape(needle)), haystack)]
[0, 2]