Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Python, how do you find the index of the first value greater than a threshold in a sorted list?

In Python, how do you find the index of the first value greater than a threshold in a sorted list?

I can think of several ways of doing this (linear search, hand-written dichotomy,..), but I'm looking for a clean an reasonably efficient way of doing it. Since it's probably a pretty common problem, I'm sure experienced SOers can help!

Thanks!

like image 459
static_rtti Avatar asked Sep 02 '11 09:09

static_rtti


People also ask

How do you find the first index of an element in a list Python?

To find index of the first occurrence of an element in a given Python List, you can use index() method of List class with the element passed as argument. The index() method returns an integer that represents the index of first match of specified element in the List.

How do you find the index value of a element in a list Python?

To find the index of an element in a list, you use the index() function. It returns 3 as expected. However, if you attempt to find an element that doesn't exist in the list using the index() function, you'll get an error. To fix this issue, you need to use the in operator.

How do you find the index number in Python?

To facilitate this, Python has an inbuilt function called index(). This function takes in the element as an argument and returns the index. By using this function we are able to find the index of an element in a list in Python.

How do you find the index of the minimum value of a list in Python?

The python has a built-in function of min() which returns the minimum value in the list and index() which returns the index of the element. These two functions can be used to find the index of a minimum element in a single line code.


2 Answers

Have a look at bisect.

import bisect  l = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]  bisect.bisect(l, 55) # returns 7 

Compare it with linear search:

timeit bisect.bisect(l, 55) # 375ns   timeit next((i for i,n in enumerate(l) if n > 55), len(l)) # 2.24us   timeit next((l.index(n) for n in l if n > 55), len(l)) # 1.93us 
like image 172
eumiro Avatar answered Oct 14 '22 09:10

eumiro


You might get a better time than the enumerate/generator approach using itertools; I think itertools provides faster implementations of the underlying algorithms, for the performance mongers in all of us. But bisect may still be faster.

from itertools import islice, dropwhile  threshold = 5 seq = [1,4,6,9,11] first_val = islice(dropwhile(lambda x: x<=threshold, seq),0,1) result = seq.index(first_val) 

I wonder about the difference between the bisect approach shown here and the one listed for your question in the doc examples, as far as idiom/speed. They show an approach for finding the value, but truncated to first line, it returns the index. I'd guess that since it's called "bisect_right" instead of "bisect," it probably only looks from one direction. Given that your list is sorted and you want greater-than, this might be the greatest search economy.

from bisect import bisect_right  def find_gt(a, x):     'Find leftmost value(switching this to index) greater than x'     return bisect_right(a, x) 

Interesting question.

like image 41
Profane Avatar answered Oct 14 '22 10:10

Profane