Reputation: 23381
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 list items, and not just at the whole items, how do I make the most Pythoninc 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
.
Upvotes: 56
Views: 86756
Reputation: 5292
I wanted to just get the text and not raise exception if item was not found
search = 'a'
next((s for s in ["aa",'c'] if search in s), None)
search = 'b'
next((el for el in ["aa",'c'] if search in el), None)
It's one of those things I wish was just implemented natively.
Upvotes: 1
Reputation: 1
@kennytm offers a great answer that helped me; to build from theirs a function that allows regex, I wrote:
def substringindex(inputlist, inputsubstring):
s = [x for x in inputlist if re.search(inputsubstring, x)]
if s != []:
return (inputlist.index(s[0]), s[0])
return -1
This function works exactly like theirs, but supports regex.
Upvotes: 0
Reputation: 1
Using map function:
index = np.nonzero(map(lambda x: substring in x, strings))[0][0]
Upvotes: 0
Reputation: 2997
With a one-liner:
index = [idx for idx, s in enumerate(l) if 'tiger' in s][0]
Upvotes: 40
Reputation: 76
imho with this line, you'll find only the first occurence without processing the whole list
index = next((i for i in enumerate(l) if "tiger" in i[1]),[-1,-1])[0]
Upvotes: 2
Reputation: 407
>>> li = ['my','array','with','words']
>>> reduce(lambda tup, word: (tup[0], True) if not tup[1] and word == 'my' else (tup[0]+1 if not tup[1] else tup[0], tup[1]), li, (0, False))[0]
0
>>> reduce(lambda tup, word: (tup[0], True) if not tup[1] and word == 'words' else (tup[0]+1 if not tup[1] else tup[0], tup[1]), li, (0, False))[0]
3
Upvotes: 0
Reputation: 304493
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()
Upvotes: 9
Reputation: 73028
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.
Upvotes: 2
Reputation: 523794
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
Upvotes: 43
Reputation: 38683
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).
Upvotes: 3
Reputation: 4882
def find(l, s):
for i in range(len(l)):
if l[i].find(s)!=-1:
return i
return None # Or -1
Upvotes: 3