Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate through positions of a substring in a string

I'm looking for the simplest way how to iterate over the positions of a substring in a string. Currently I'm using a generator for that, but I have a feeling that it's not quite Pythonian:

def iteratePos(haystack, needle) :
    pos = haystack.find(needle)
    while pos >= 0 :
        yield pos
        pos = haystack.find(needle, pos+1)

s = "ABC 11 ABC 111 ABC 1"
for i in iteratePos(s, "ABC") :
    print "aye bee see at", i
    # finds 0, 7, 15

for i in iteratePos(s, "1") :
    print "one at", i
    # finds 4, 5, 11, 12, 13, 19

So, is it possible to do this as a reasonable one-liner? Or should I stick to the solution I have?

(Note: Should there be a simple solution for the case when needle is just one character, I'm interested in that as well.)

like image 215
yo' Avatar asked Jan 31 '15 00:01

yo'


People also ask

How do I iterate through a substring?

You can traverse a string as a substring by using the Python slice operator ([]). It cuts off a substring from the original string and thus allows to iterate over it partially. To use this method, provide the starting and ending indices along with a step value and then traverse the string.

How do you find the position of a substring in a string in Python?

Python String find() method returns the lowest index or first occurrence of the substring if it is found in a given string. If it is not found, then it returns -1. Parameters: sub: Substring that needs to be searched in the given string.

Can you loop through a string?

Loops can be used to traverse or process a string.


2 Answers

s = "ABC 11 ABC 111 ABC 1"

print([ind for ind,_ in enumerate(s[:-2]) if s[ind:ind+3] == "ABC"])
[0, 7, 15]

In a function:

def iteratePos(haystack, needle) :
    ln = len(needle)
    return [ind for ind,_ in enumerate(s[:-ln-1]) if haystack[ind:ind+ln] == needle]

Or using yield from in Python 3:

def iteratePos(haystack, needle) :
    ln = len(needle)
    yield from (ind for ind, _ in enumerate(haystack[:-ln-1]) if haystack[ind:ind+ln] == needle)
print(next(iteratePos(s,"ABC")))
0
like image 90
Padraic Cunningham Avatar answered Oct 05 '22 13:10

Padraic Cunningham


I think your solution is fine ... but I guess you could do

[i for i in range(len(s)) if s[i:].startswith(needle)]

if you really dont like your solution

like image 23
Joran Beasley Avatar answered Oct 05 '22 12:10

Joran Beasley