Python: Find a substring in a string and returning the index of the substring

231,622

Solution 1

Ideally you would use str.find or str.index like demented hedgehog said. But you said you can't ...

Your problem is your code searches only for the first character of your search string which(the first one) is at index 2.

You are basically saying if char[0] is in s, increment index until ch == char[0] which returned 3 when I tested it but it was still wrong. Here's a way to do it.

def find_str(s, char):
    index = 0

    if char in s:
        c = char[0]
        for ch in s:
            if ch == c:
                if s[index:index+len(char)] == char:
                    return index

            index += 1

    return -1

print(find_str("Happy birthday", "py"))
print(find_str("Happy birthday", "rth"))
print(find_str("Happy birthday", "rh"))

It produced the following output:

3
8
-1

Solution 2

There's a builtin method find on string objects.

s = "Happy Birthday"
s2 = "py"

print(s.find(s2))

Python is a "batteries included language" there's code written to do most of what you want already (whatever you want).. unless this is homework :)

find returns -1 if the string cannot be found.

Solution 3

There is one other option in regular expression, the search method

import re

string = 'Happy Birthday'
pattern = 'py'
print(re.search(pattern, string).span()) ## this prints starting and end indices
print(re.search(pattern, string).span()[0]) ## this does what you wanted

By the way, if you would like to find all the occurrence of a pattern, instead of just the first one, you can use finditer method

import re

string = 'i think that that that that student wrote there is not that right'
pattern = 'that'

print([match.start() for match in re.finditer(pattern, string)])

which will print all the starting positions of the matches.

Solution 4

Adding onto @demented hedgehog answer on using find()

In terms of efficiency

It may be worth first checking to see if s1 is in s2 before calling find().
This can be more efficient if you know that most of the times s1 won't be a substring of s2

Since the in operator is very efficient

 s1 in s2

It can be more efficient to convert:

index = s2.find(s1)

to

index = -1
if s1 in s2:
   index = s2.find(s1)

This is useful for when find() is going to be returning -1 a lot.

I found it substantially faster since find() was being called many times in my algorithm, so I thought it was worth mentioning

Solution 5

Here is a simple approach:

my_string = 'abcdefg'
print(text.find('def'))

Output:

3

I the substring is not there, you will get -1. For example:

my_string = 'abcdefg'
print(text.find('xyz'))

Output:

-1

Sometimes, you might want to throw exception if substring is not there:

my_string = 'abcdefg'
print(text.index('xyz')) # It returns an index only if it's present

Output:

Traceback (most recent call last):

File "test.py", line 6, in print(text.index('xyz'))

ValueError: substring not found

Share:
231,622
Tyler
Author by

Tyler

Updated on July 05, 2022

Comments

  • Tyler
    Tyler almost 2 years

    I have:

    • a function: def find_str(s, char)

    • and a string: "Happy Birthday",

    I essentially want to input "py" and return 3 but I keep getting 2 to return instead.

    Code:

    def find_str(s, char):
        index = 0           
        if char in s:
            char = char[0]
            for ch in s:
                if ch in s:
                    index += 1
                if ch == char:
                    return index
    
        else:
            return -1
    
    print(find_str("Happy birthday", "py"))
    

    Not sure what's wrong!

  • Tyler
    Tyler about 10 years
    I need to write an algorithm that does the .find function. I can't just use it unfortunately!
  • Eric Fortin
    Eric Fortin about 10 years
    @Tyler Edited my answer since there wasn't an actual answer to your question.
  • Kev1n91
    Kev1n91 about 7 years
    there is a better method like suggested by @demented hedgehog. This should be the accepted answer
  • Eric Fortin
    Eric Fortin about 7 years
    @Kev1n91 I know and I said it in my answer but OP comment he couldn't use it.
  • Ver Nick
    Ver Nick over 5 years
    @Kev1n91 That is really strange it wasn't accepted.
  • demented hedgehog
    demented hedgehog over 5 years
    I answered the question after the original answer was accepted. I just happened upon it and thought I'd add my two cents worth.
  • pdaawr
    pdaawr over 3 years
    It wasn't accepted because @Tyler couldn't use str.find or str.index