tags:

views:

331

answers:

5

For lists the method list.index(x) returns the index in the list of the first item whose value is x. But if I want to look inside the items, and not just at the whole items, how do I make the slickest Python method for this?

For example, with

l = ['the cat ate the mouse','the tiger ate the chicken','the horse ate the straw']

this function would return 1 provided with the argument tiger.

+3  A: 

A non-slicky method:

def index_containing_substring(the_list, substring):
    for i, s in enumerate(the_list):
        if substring in s:
              return i
    return -1
KennyTM
Slicker than mine I'd say. +1~
Etienne Perot
A: 
def find(l, s):
    for i in range(len(l)):
        if l[i].find(s)!=-1:
            return i
    return None # Or -1
Etienne Perot
A: 

This is quite slick and fairly efficient.

>>> def find(lst, predicate):
...     return (i for i, j in enumerate(lst) if predicate(j)).next()
... 
>>> l = ['the cat ate the mouse','the tiger ate the chicken','the horse ate the straw']
>>> find(l, lambda x: 'tiger' in x)
1

Only problem is that it will raise StopIteration if the item is not found (though that is easily remedied).

Max Shawabkeh
A: 
def first_substring(strings, substring):
    return min(i for i, string in enumerate(strings) if substring in string)

Note: This will raise ValueError in case no match is found, which is better in my opinion.

abyx
Fancy but not efficient, as it tests all elements of the list regardless of whether the text has been found previously or not.Also, Python's 'something'.find(s) function returns -1 when no match is found, so I'd call that Pythonic.
Etienne Perot
Does not work, at least in Python 2.6. You can't use both an iterable and an extra argument in `min()`. @Etiene: this is a generator expression, not a list comprehension, so it wouldn't generate everything.
Max Shawabkeh
@Etienne - premature optimization is the root of all evil etc.@Max - you are correct, fixed.
abyx
A: 

Variation of abyx solution (optimised to stop when the match is found)

def first_substring(strings, substring):
    return next(i for i, string in enumerate(strings) if substring in string)

If you are pre 2.6 you'll need to put the next() at the end

def first_substring(strings, substring):
    return (i for i, string in enumerate(strings) if substring in string).next()
gnibbler