First Python list index greater than x?
Question:
What would be the most Pythonic way to find the first index in a list that is greater than x?
For example, with
list = [0.5, 0.3, 0.9, 0.8]
The function
f(list, 0.7)
would return
2.
Answers:
>>> f=lambda seq, m: [ii for ii in xrange(0, len(seq)) if seq[ii] > m][0]
>>> f([.5, .3, .9, .8], 0.7)
2
next(x[0] for x in enumerate(L) if x[1] > 0.7)
for index, elem in enumerate(elements):
if elem > reference:
return index
raise ValueError("Nothing Found")
>>> alist= [0.5, 0.3, 0.9, 0.8]
>>> [ n for n,i in enumerate(alist) if i>0.7 ][0]
2
Another one:
map(lambda x: x>.7, seq).index(True)
filter(lambda x: x>.7, seq)[0]
if list is sorted then bisect.bisect_left(alist, value)
is faster for a large list than next(i for i, x in enumerate(alist) if x >= value)
.
I had similar problem when my list was very long. Comprehension or filter-based solutions would go through the whole list. Instead itertools.takewhile
will break the loop once the condition is false for the first time:
from itertools import takewhile
def f(l, b): return len([x for x in takewhile(lambda x: x[1] <= b, enumerate(l))])
l = [0.5, 0.3, 0.9, 0.8]
f(l, 0.7)
I know there are already plenty of answers, but I sometimes I feel that the word pythonic is translated into ‘one-liner’.
When I think a better definition is closer to this answer:
“Exploiting the features of the Python language to produce code that is clear, concise and maintainable.”
While some of the above answers are concise, I do not find them to be clear and it would take a newbie programmer a while to understand, therefore not making them extremely maintainable for a team built of many skill levels.
l = [0.5, 0.3, 0.9, 0.8]
def f(l, x):
for i in l:
if i >x: break
return l.index(i)
f(l,.7)
or
l = [0.5, 0.3, 0.9, 0.8]
def f(l, x):
for i in l:
if i >x: return l.index(i)
f(l,.7)
I think the above is easily understood by a newbie and is still concise enough to be accepted by any veteran python programmer.
I think writing dumb code is a positive.
Try this one:
def Renumerate(l):
return [(len(l) - x, y) for x,y in enumerate(l)]
example code:
Renumerate(range(10))
output:
(10, 0)
(9, 1)
(8, 2)
(7, 3)
(6, 4)
(5, 5)
(4, 6)
(3, 7)
(2, 8)
(1, 9)
1) NUMPY ARGWHERE, general lists
If you are happy to use numpy (imported as np
here), then the following will work on general lists (sorted or unsorted):
np.argwhere(np.array(searchlist)>x)[0]
or if you need the answer as a integer index:
np.argwhere(np.array(searchlist)>x)[0][0]
2) NUMPY SEARCHSORTED, sorted lists (very efficient for searching lists within a list)
However, if your search list [l1,l2,…] is sorted, it is much cleaner and nicer to use the function np.searchsorted:
np.searchsorted(searchlist,x)
The nice thing about using this function is that as well as searching for a single value x within the search list [l1,l2,…], you can also search for a list of values [x1,x2,x3…xn] within your search list (i.e. x can be a list too, and it is extremely efficient relative to a list comprehension in this case).
You could also do this using numpy
:
import numpy as np
list(np.array(SearchList) > x).index(True)
What would be the most Pythonic way to find the first index in a list that is greater than x?
For example, with
list = [0.5, 0.3, 0.9, 0.8]
The function
f(list, 0.7)
would return
2.
>>> f=lambda seq, m: [ii for ii in xrange(0, len(seq)) if seq[ii] > m][0]
>>> f([.5, .3, .9, .8], 0.7)
2
next(x[0] for x in enumerate(L) if x[1] > 0.7)
for index, elem in enumerate(elements):
if elem > reference:
return index
raise ValueError("Nothing Found")
>>> alist= [0.5, 0.3, 0.9, 0.8]
>>> [ n for n,i in enumerate(alist) if i>0.7 ][0]
2
Another one:
map(lambda x: x>.7, seq).index(True)
filter(lambda x: x>.7, seq)[0]
if list is sorted then bisect.bisect_left(alist, value)
is faster for a large list than next(i for i, x in enumerate(alist) if x >= value)
.
I had similar problem when my list was very long. Comprehension or filter-based solutions would go through the whole list. Instead itertools.takewhile
will break the loop once the condition is false for the first time:
from itertools import takewhile
def f(l, b): return len([x for x in takewhile(lambda x: x[1] <= b, enumerate(l))])
l = [0.5, 0.3, 0.9, 0.8]
f(l, 0.7)
I know there are already plenty of answers, but I sometimes I feel that the word pythonic is translated into ‘one-liner’.
When I think a better definition is closer to this answer:
“Exploiting the features of the Python language to produce code that is clear, concise and maintainable.”
While some of the above answers are concise, I do not find them to be clear and it would take a newbie programmer a while to understand, therefore not making them extremely maintainable for a team built of many skill levels.
l = [0.5, 0.3, 0.9, 0.8]
def f(l, x):
for i in l:
if i >x: break
return l.index(i)
f(l,.7)
or
l = [0.5, 0.3, 0.9, 0.8]
def f(l, x):
for i in l:
if i >x: return l.index(i)
f(l,.7)
I think the above is easily understood by a newbie and is still concise enough to be accepted by any veteran python programmer.
I think writing dumb code is a positive.
Try this one:
def Renumerate(l):
return [(len(l) - x, y) for x,y in enumerate(l)]
example code:
Renumerate(range(10))
output:
(10, 0)
(9, 1)
(8, 2)
(7, 3)
(6, 4)
(5, 5)
(4, 6)
(3, 7)
(2, 8)
(1, 9)
1) NUMPY ARGWHERE, general lists
If you are happy to use numpy (imported as np
here), then the following will work on general lists (sorted or unsorted):
np.argwhere(np.array(searchlist)>x)[0]
or if you need the answer as a integer index:
np.argwhere(np.array(searchlist)>x)[0][0]
2) NUMPY SEARCHSORTED, sorted lists (very efficient for searching lists within a list)
However, if your search list [l1,l2,…] is sorted, it is much cleaner and nicer to use the function np.searchsorted:
np.searchsorted(searchlist,x)
The nice thing about using this function is that as well as searching for a single value x within the search list [l1,l2,…], you can also search for a list of values [x1,x2,x3…xn] within your search list (i.e. x can be a list too, and it is extremely efficient relative to a list comprehension in this case).
You could also do this using numpy
:
import numpy as np
list(np.array(SearchList) > x).index(True)