What is the most efficient way to find substrings in strings?
Does Python have a string 'contains' substring method? - Stack Overflow
python - How to find all occurrences of a substring? - Stack Overflow
How to find all occurrences of a substring in a string while ignore some characters in Python?
Videos
Hello,
There are several ways to find substrings in string, You could use substring in string you could use string.index(substring), or you could use string.find(substring) or even use regex.
I'm trying to understand if there is a significant difference between them for my use case, which is finding people names in article titles for example:
I want to check if Leonardo DiCaprio is in Leonardo DiCaprio gets called out for boarding superyacht: ‘eco-hypocrite’
What I usually do is:
def is_substring_in_string(substring: str, string: str):
#same thing as before but on the article title.
string_alphanumeric = ''.join(e for e in string if e.isalnum()).lower()
return substring in string_alphanumeric
def main():
names = ["Harrison Ford","Leonardo DiCaprio","Eddie Murphy","Bruce Willis","Will Smith"]
#removes unwanted charecters such as !@#$%^&*() etc and converts to lower case
names_alnum_lower = [''.join(e for e in x if e.isalnum()).lower() for x in names]
article_title = "Leonardo DiCaprio gets called out for boarding superyacht: eco-hypocrite"
for idx, lower_name in enumerate(names_alnum_lower):
if is_substring_in_string(lower_name,article_title):
print(f"Actor Name: '{names[idx]}' is in article title '{article_title}'")
if __name__ == '__main__':
main()Imagine there are a bunch of articles and people's names. Is this method acceptable or will I be better off using regex or something else?
Use the in operator:
if "blah" not in somestring:
continue
Note: This is case-sensitive.
You can use str.find:
s = "This be a string"
if s.find("is") == -1:
print("Not found")
else:
print("Found")
The
find()method should be used only if you need to know the position of sub. To check if sub is a substring or not, use theinoperator. (c) Python reference
There is no simple built-in string function that does what you're looking for, but you could use the more powerful regular expressions:
import re
[m.start() for m in re.finditer('test', 'test test test test')]
#[0, 5, 10, 15]
If you want to find overlapping matches, lookahead will do that:
[m.start() for m in re.finditer('(?=tt)', 'ttt')]
#[0, 1]
If you want a reverse find-all without overlaps, you can combine positive and negative lookahead into an expression like this:
search = 'tt'
[m.start() for m in re.finditer('(?=%s)(?!.{1,%d}%s)' % (search, len(search)-1, search), 'ttt')]
#[1]
re.finditer returns a generator, so you could change the [] in the above to () to get a generator instead of a list which will be more efficient if you're only iterating through the results once.
>>> help(str.find)
Help on method_descriptor:
find(...)
S.find(sub [,start [,end]]) -> int
Thus, we can build it ourselves:
def find_all(a_str, sub):
start = 0
while True:
start = a_str.find(sub, start)
if start == -1: return
yield start
start += len(sub) # use start += 1 to find overlapping matches
list(find_all('spam spam spam spam', 'spam')) # [0, 5, 10, 15]
No temporary strings or regexes required.