Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding All Positions Of A Character In A String

I'm trying to find all the index numbers of a character in a python string using a very basic skill set. For example if I have the string "Apples are totally awesome" and I want to find the places where 'a' is in the string. My ideal output would be:

0
7
14
19

These are all the places in the string that an 'a' appears (I think)

This is the code I have so far:

sentence = input("Input a string: ")
for ch in sentence:
    x = sentence.find('o')


print(x)

Here I'm looking for 'o' instead of a. My thought process is that for each character in the string the find function will return the position of the 'o'. Since I don't know how long the input string will be necessarily I used a for loop. I'm able to find and print out the first instance of an 'o' but not all of them. What should I do? Thanks in advance!

like image 460
Amaranthus Avatar asked Jan 01 '23 20:01

Amaranthus


1 Answers

Using enumerate is the standard way to go. Although, you can take advantage of the speed of str.find for time-critical operations.

Code

def find_all(s, c):
    idx = s.find(c)
    while idx != -1:
        yield idx
        idx = s.find(c, idx + 1)

print(*find_all('Apples are totally awesome', 'o')) # 12 23

I made the above return a generator for elegance and to account for very large strings. Put it can of course be casted to a list if need be.

Benchmark

Here is a benchmark against a solution using enumerate and a list-comprehension. Both solutions have linear time-complexity, but str.find is significantly faster.

import timeit

def find_all_enumerate(s, c):
    return [i for i, x in enumerate(s) if c == x]

print(
    'find_all:',
    timeit.timeit("list(find_all('Apples are totally awesome', 'o'))",
                  setup="from __main__ import find_all")
)

print(
    'find_all_enumerate:',
    timeit.timeit("find_all_enumerate('Apples are totally awesome', 'o')",
                  setup="from __main__ import find_all_enumerate")
)

Output

find_all: 1.1554179692960915
find_all_enumerate: 1.9171753468076869
like image 65
Olivier Melançon Avatar answered Jan 13 '23 13:01

Olivier Melançon