719

How can I get the position of a character inside a string in Python?

bad_coder
  • 11,289
  • 20
  • 44
  • 72
user244470
  • 7,469
  • 4
  • 17
  • 10

11 Answers11

921

There are two string methods for this, find() and index(). The difference between the two is what happens when the search string isn't found. find() returns -1 and index() raises a ValueError.

Using find()

>>> myString = 'Position of a character'
>>> myString.find('s')
2
>>> myString.find('x')
-1

Using index()

>>> myString = 'Position of a character'
>>> myString.index('s')
2
>>> myString.index('x')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: substring not found

From the Python manual

string.find(s, sub[, start[, end]])
Return the lowest index in s where the substring sub is found such that sub is wholly contained in s[start:end]. Return -1 on failure. Defaults for start and end and interpretation of negative values is the same as for slices.

And:

string.index(s, sub[, start[, end]])
Like find() but raise ValueError when the substring is not found.

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
180

Just for a sake of completeness, if you need to find all positions of a character in a string, you can do the following:

s = 'shak#spea#e'
c = '#'
print([pos for pos, char in enumerate(s) if char == c])

which will print: [4, 9]

Jolbas
  • 757
  • 5
  • 15
Salvador Dali
  • 214,103
  • 147
  • 703
  • 753
  • 4
    `foo = ( [pos for pos, char in enumerate(s) if char == c])` will put the coordinates **foo** in a list format. I find this really helpful – 3nrique0 Feb 24 '17 at 17:01
  • it's 0 indexed, 0123 as opposed 1234, so the actual position is 5, 10 – 3kstc Jan 06 '20 at 04:47
60
>>> s="mystring"
>>> s.index("r")
4
>>> s.find("r")
4

"Long winded" way

>>> for i,c in enumerate(s):
...   if "r"==c: print i
...
4

to get substring,

>>> s="mystring"
>>> s[4:10]
'ring'
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
21

Just for completion, in the case I want to find the extension in a file name in order to check it, I need to find the last '.', in this case use rfind:

path = 'toto.titi.tata..xls'
path.find('.')
4
path.rfind('.')
15

in my case, I use the following, which works whatever the complete file name is:

filename_without_extension = complete_name[:complete_name.rfind('.')]
A.Joly
  • 2,317
  • 2
  • 20
  • 25
  • This is helpful for finding the extent of a string. For example, finding a dictionary could be: `left = q.find("{"); right = q.rfind("}")`. – ximiki Oct 06 '17 at 16:51
  • If you're trying to find the extension of a filename, the better way to do it now would probably be with Pathlib. `from pathlib import Path; p = Path("toto.titi.tata..xls")`. Then `p.suffix == ".xls"` and `p.stem == "toto.titi.tata."` – nigh_anxiety May 16 '23 at 17:06
17

What happens when the string contains a duplicate character? from my experience with index() I saw that for duplicate you get back the same index.

For example:

s = 'abccde'
for c in s:
    print('%s, %d' % (c, s.index(c)))

would return:

a, 0
b, 1
c, 2
c, 2
d, 4

In that case you can do something like that:

for i, character in enumerate(my_string):
   # i is the position of the character in the string
Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146
DimSarak
  • 452
  • 2
  • 5
  • 11
14
string.find(character)  
string.index(character)  

Perhaps you'd like to have a look at the documentation to find out what the difference between the two is.

Brad Koch
  • 19,267
  • 19
  • 110
  • 137
John Machin
  • 81,303
  • 11
  • 141
  • 189
  • From that linked documentation: s.search() raises a ValueError when the substring is not found. s.find() returns -1 if the substring isn't found. – Praxiteles Jan 29 '17 at 09:10
8

A character might appear multiple times in a string. For example in a string sentence, position of e is 1, 4, 7 (because indexing usually starts from zero). but what I find is both of the functions find() and index() returns first position of a character. So, this can be solved doing this:

def charposition(string, char):
    pos = [] #list to store positions for each 'char' in 'string'
    for n in range(len(string)):
        if string[n] == char:
            pos.append(n)
    return pos

s = "sentence"
print(charposition(s, 'e')) 

#Output: [1, 4, 7]
itssubas
  • 163
  • 2
  • 11
6

If you want to find the first match.

Python has a in-built string method that does the work: index().

string.index(value, start, end)

Where:

  • Value: (Required) The value to search for.
  • start: (Optional) Where to start the search. Default is 0.
  • end: (Optional) Where to end the search. Default is to the end of the string.
def character_index():
    string = "Hello World! This is an example sentence with no meaning."
    match = "i"
    return string.index(match)
        
print(character_index())
> 15

If you want to find all the matches.

Let's say you need all the indexes where the character match is and not just the first one.

The pythonic way would be to use enumerate().

def character_indexes():
    string = "Hello World! This is an example sentence with no meaning."
    match = "i"

    indexes_of_match = []

    for index, character in enumerate(string):
        if character == match:
            indexes_of_match.append(index)
    return indexes_of_match

print(character_indexes())
# [15, 18, 42, 53]

Or even better with a list comprehension:

def character_indexes_comprehension():
    string = "Hello World! This is an example sentence with no meaning."
    match = "i"

    return [index for index, character in enumerate(string) if character == match]


print(character_indexes_comprehension())
# [15, 18, 42, 53]
Guzman Ojero
  • 2,812
  • 1
  • 20
  • 20
4

more_itertools.locate is a third-party tool that finds all indicies of items that satisfy a condition.

Here we find all index locations of the letter "i".

Given

import more_itertools as mit


text = "supercalifragilisticexpialidocious"
search = lambda x: x == "i"

Code

list(mit.locate(text, search))
# [8, 13, 15, 18, 23, 26, 30]
pylang
  • 40,867
  • 14
  • 129
  • 121
1

Most methods I found refer to finding the first substring in a string. To find all the substrings, you need to work around.

For example:

Define the string

vars = 'iloveyoutosimidaandilikeyou'

Define the substring

key = 'you'

Define a function that can find the location for all the substrings within the string

def find_all_loc(vars, key):

    pos = []
    start = 0
    end = len(vars)

    while True: 
        loc = vars.find(key, start, end)
        if  loc is -1:
            break
        else:
            pos.append(loc)
            start = loc + len(key)
            
    return pos

pos = find_all_loc(vars, key)

print(pos)
[5, 24]
Emi OB
  • 2,814
  • 3
  • 13
  • 29
Chan Kin Sung
  • 71
  • 1
  • 2
0

A solution with numpy for quick access to all indexes:

string_array = np.array(list(my_string))
char_indexes = np.where(string_array == 'C')
Seb
  • 312
  • 4
  • 6