find all index positions

John Machin sjmachin at lexicon.net
Fri May 12 00:58:16 CEST 2006


On 12/05/2006 5:13 AM, vbgunz wrote:
> I thought this to be a great exercise so I went the extra length to
> turn it into a function for my little but growing library. I hope you
> enjoy :)
> 

Oh, indeed ;-)

> 
> def indexer(string, target):

Consider not shadowing the name of the string module.

>     '''indexer(string, target) -> [list of target indexes]
> 
>     enter in a string and a target and indexer will either return a
>     list of all targeted indexes if at least one target is found or
>     indexer will return None if the target is not found in sequence.

Consider returning [] if the target is not found in the sequence. That 
would enable callers to "do nothing gracefully":

for posn in indexer(...
     # do something

and it doesn't require a gross rewrite ... merely dedent the last line.

> 
>     >>> indexer('a long long day is long', 'long')
>     [2, 7, 19]
> 
>     >>> indexer('a long long day is long', 'day')
>     [12]
> 
>     >>> indexer('a long long day is long', 'short')
>     None
>     '''
> 
>     res = []
> 

Consider evaluating string.count(target) *ONCE*.

>     if string.count(target) >= 1:
>         res.append(string.find(target))
> 
>         if string.count(target) >= 2:
>             for item in xrange(string.count(target) - 1):
>                 res.append(string.find(target, res[-1] + 1))
> 
>         return res
> 
> 
> if __name__ == '__main__':
>     print indexer('a long long day is long', 'long')    # -> [2, 7, 19]
>     print indexer('a long long day is long', 'day')     # -> [12]
>     print indexer('a long long day is long', 'short')   # -> None
> 

When called with the args('abababababababa', 'aba'), it returns [0, 2, 
4, 6]. If you *intend* to allow for overlaps, it should return [0, 2, 4, 
6, 8, 10, 12]; otherwise it should return [0, 4, 8, 12].

Consider doing something straightforward and understandable, like the 
following (tested):

def findallstr(text, target, overlapping=0):
     result = []
     startpos = 0
     if overlapping:
         jump = 1
     else:
         jump = max(1, len(target))
     while 1:
         newpos = text.find(target, startpos)
         if newpos == -1:
             return result
         result.append(newpos)
         startpos = newpos + jump

HTH,
John



More information about the Python-list mailing list