Python: Find index of minimum item in list of floats

PythonListFloating PointMinimumFloating Point-Precision

Python Problem Overview


How can I find the index of the minimum item in a Python list of floats? If they were integers, I would simply do:

minIndex = myList.index(min(myList))

However, with a list of floats I get the following error, I assume because float equality comparison is rather iffy.

ValueError: 0.13417985135 is not in list

Now, I know that I could simply scroll through the list and compare each item to see whether it is < (min + 0.0000000000001) and > (min - 0.0000000000001), but that is kinda messy. Is there a more elegant (preferably built-in) way to find the index of the smallest item in a list of floats?

Python Solutions


Solution 1 - Python

I would use:

val, idx = min((val, idx) for (idx, val) in enumerate(my_list))

Then val will be the minimum value and idx will be its index.

Solution 2 - Python

You're effectively scanning the list once to find the min value, then scanning it again to find the index, you can do both in one go:

from operator import itemgetter
min(enumerate(a), key=itemgetter(1))[0] 

Solution 3 - Python

Use of the argmin method for numpy arrays.

import numpy as np
np.argmin(myList)

However, it is not the fastest method: it is 3 times slower than OP's answer on my computer. It may be the most concise one though.

Solution 4 - Python

I think it's worth putting a few timings up here for some perspective.

All timings done on OS-X 10.5.8 with python2.7

John Clement's answer:

python -m timeit -s 'my_list = range(1000)[::-1]; from operator import itemgetter' 'min(enumerate(my_list),key=itemgetter(1))'
1000 loops, best of 3: 239 usec per loop    

David Wolever's answer:

python -m timeit -s 'my_list = range(1000)[::-1]' 'min((val, idx) for (idx, val) in enumerate(my_list))
1000 loops, best of 3: 345 usec per loop

OP's answer:

python -m timeit -s 'my_list = range(1000)[::-1]' 'my_list.index(min(my_list))'
10000 loops, best of 3: 96.8 usec per loop

Note that I'm purposefully putting the smallest item last in the list to make .index as slow as it could possibly be. It would be interesting to see at what N the iterate once answers would become competitive with the iterate twice answer we have here.

Of course, speed isn't everything and most of the time, it's not even worth worrying about ... choose the one that is easiest to read unless this is a performance bottleneck in your code (and then profile on your typical real-world data -- preferably on your target machines).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionthornateView Question on Stackoverflow
Solution 1 - PythonDavid WoleverView Answer on Stackoverflow
Solution 2 - PythonJon ClementsView Answer on Stackoverflow
Solution 3 - PythonAlexPView Answer on Stackoverflow
Solution 4 - PythonmgilsonView Answer on Stackoverflow