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
Answer from kennytm on Stack Overflowpython - Get first list index containing sub-string? - Stack Overflow
python - How can I find the index for a given item in a list? - Stack Overflow
python - Finding the index of the element contains string in a list - Stack Overflow
python - Find all index position in list based on partial string inside item in list - Stack Overflow
Videos
>>> ["foo", "bar", "baz"].index("bar")
1
See the documentation for the built-in .index() method of the list:
list.index(x[, start[, end]])Return zero-based index in the list of the first item whose value is equal to x. Raises a
ValueErrorif there is no such item.The optional arguments start and end are interpreted as in the slice notation and are used to limit the search to a particular subsequence of the list. The returned index is computed relative to the beginning of the full sequence rather than the start argument.
Caveats
Linear time-complexity in list length
An index call checks every element of the list in order, until it finds a match. If the list is long, and if there is no guarantee that the value will be near the beginning, this can slow down the code.
This problem can only be completely avoided by using a different data structure. However, if the element is known to be within a certain part of the list, the start and end parameters can be used to narrow the search.
For example:
>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514
The second call is orders of magnitude faster, because it only has to search through 10 elements, rather than all 1 million.
Only the index of the first match is returned
A call to index searches through the list in order until it finds a match, and stops there. If there could be more than one occurrence of the value, and all indices are needed, index cannot solve the problem:
>>> [1, 1].index(1) # the `1` index is not found.
0
Instead, use a list comprehension or generator expression to do the search, with enumerate to get indices:
>>> # A list comprehension gives a list of indices directly:
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> # A generator comprehension gives us an iterable object...
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> # which can be used in a `for` loop, or manually iterated with `next`:
>>> next(g)
0
>>> next(g)
2
The list comprehension and generator expression techniques still work if there is only one match, and are more generalizable.
Raises an exception if there is no match
As noted in the documentation above, using .index will raise an exception if the searched-for value is not in the list:
>>> [1, 1].index(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 2 is not in list
If this is a concern, either explicitly check first using item in my_list, or handle the exception with try/except as appropriate.
The explicit check is simple and readable, but it must iterate the list a second time. See What is the EAFP principle in Python? for more guidance on this choice.
The majority of answers explain how to find a single index, but their methods do not return multiple indexes if the item is in the list multiple times. Use enumerate():
for i, j in enumerate(['foo', 'bar', 'baz']):
if j == 'bar':
print(i)
The index() function only returns the first occurrence, while enumerate() returns all occurrences.
As a list comprehension:
[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']
Here's also another small solution with itertools.count() (which is pretty much the same approach as enumerate):
from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']
This is more efficient for larger lists than using enumerate():
$ python -m timeit -s "from itertools import izip as zip, count" "[i for i, j in zip(count(), ['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 174 usec per loop
$ python -m timeit "[i for i, j in enumerate(['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 196 usec per loop
Use isinstance():
my_list = [True, 10.8, [1,2,3], False, True, "Hello", 12, "Sbioer", 2.5]
for i, item in enumerate(my_list):
if isinstance(item, basestring):
print i
Output:
5
7
However, if you want to check for int values, you will get bool-type item's indexes too because (quoting text from some other source):
It is perfectly logical, if you were around when the bool type was added to python (sometime around 2.2 or 2.3).
Prior to introduction of an actual bool type, 0 and 1 were the official representation for truth value, similar to C89. To avoid unnecessarily breaking non-ideal but working code, the new bool type needed to work just like 0 and 1. This goes beyond merely truth value, but all integral operations. No one would recommend using a boolean result in a numeric context, nor would most people recommend testing equality to determine truth value, no one wanted to find out the hard way just how much existing code is that way. Thus the decision to make True and False masquerade as 1 and 0, respectively. This is merely a historical artifact of the linguistic evolution.
So if you want to check for only int values just:
my_list = [True, 10.8, [1,2,3], False, True, "Hello", 12, "Sbioer", 2.5]
for i, item in enumerate(my_list):
if isinstance(item, int) and not isinstance(item, bool):
print i
You can use a combination of enumerate() and isinstance() to get the index of the string items:
l = [1, True, 'Hello', [1, 3, False, 'nested'], 'Bye']
for i, item in enumerate(l):
if isinstance(item, basestring): # Python 2. Use (str, bytes) instead of basestring for Python 3
print i
Produces this output:
2 4
Note that this does not descend into the nested list; you will want to use recursion to do that.
You can use enumerate inside a list-comprehension:
indices = [i for i, s in enumerate(mylist) if 'aa' in s]
Your idea to use enumerate() was correct.
indices = []
for i, elem in enumerate(mylist):
if 'aa' in elem:
indices.append(i)
Alternatively, as a list comprehension:
indices = [i for i, elem in enumerate(mylist) if 'aa' in elem]
One solution is make words set instead of list and then do simple list comprehension:
words = {'must', 'shall', 'may','should','forbidden','car'}
string= 'you should wash the car every day'
out = [i for i, w in enumerate(string.split()) if w in words]
print(out)
Prints:
[1, 4]
You need the Aho Corasick algorithm to this.
Given a set of strings and a text, it finds occurrences of all strings from the set in the given text in O(len+ans), where len is the length of the text and ans is the size of the answer.
It uses an automaton and can be modified to suit your needs.
For example if I have a list
cities = ["The capital of france is Paris", "The capital of france is Berlin"," The capital of france is London"," The capital of france is Barcelona"]
How do I search the list for "Berlin" and get the index of the sentence containing "Berlin"?