I want to find the index of the n\'th occurrence of an item in a list. e.g.,
x=[False,True,True,False,True,False,True,False,False,False,True,False,True]
If you're concerned with performance, you are best off seeing if there are algorithmic optimizations you can make. For example, if you are calling this function many times on the same values, you may wish to cache previous computations (e.g. once you find the 50th occurrence of an element, you can find any previous occurrence in O(1)
time).
Otherwise, you want to make sure your technique works on (lazy) iterators.
The most *in*elegant and performance-happy way I can think of implementing it is as:
def indexOfNthOccurrence(N, element, stream):
"""for N>0, returns index or None"""
seen = 0
for i,x in enumerate(stream):
if x==element:
seen += 1
if seen==N:
return i
(if you really care about the performance difference between enumerate and other techniques, you will need to resort to profiling, especially with the numpy functions, which may resort to C)
To preprocess the entire stream and support O(1)
queries:
from collections import *
cache = defaultdict(list)
for i,elem in enumerate(YOUR_LIST):
cache[elem] += [i]
# e.g. [3,2,3,2,5,5,1]
# 0 1 2 3 4 5 6
# cache: {3:[0,2], 1:[6], 2:[1,3], 5:[4,5]}
Here is another way to find the nth
occurrence of x
in a list itrbl
:
def nthoccur(nth,x,itrbl):
count,index = 0,0
while count < nth:
if index > len(itrbl) - 1:
return None
elif itrbl[index] == x:
count += 1
index += 1
else:
index += 1
return index - 1
here is a way :
for the example above :
x=[False,True,True,False,True,False,True,False,False,False,True,False,True]
we can define a function find_index
def find_index(lst, value, n):
c=[]
i=0
for element in lst :
if element == value :
c .append (i)
i+=1
return c[n]
and if we apply the function :
nth_index = find_index(x, True, 4)
print nth_index
the result is:
10
You can use next
with enumerate
and a generator expression. itertools.islice allows you to slice an iterable as required.
from itertools import islice
x = [False,True,True,False,True,False,True,False,False,False,True,False,True]
def get_nth_index(L, val, n):
"""return index of nth instance where value in list equals val"""
return next(islice((i for i, j in enumerate(L) if j == val), n-1, n), -1)
res = get_nth_index(x, True, 3) # 4
If the iterator is exhausted, i.e. the nth occurrence of the specified value doesn't exist, next
can return a default value, in this instance -1
:
[y for y in enumerate(x) if y[1]==True][z][0]
Note: Here Z is the n'th occurance,