web-dev-qa-db-fra.com

Python: recherche l'index de l'élément minimum dans la liste des flottants

Comment puis-je trouver l'index de l'élément minimum dans une liste de flotteurs Python? S'il s'agissait d'entiers, je ferais simplement:

minIndex = myList.index(min(myList))

Cependant, avec une liste de flottants, j'obtiens l'erreur suivante, je suppose que la comparaison d'égalité des flotteurs est plutôt incertaine.

ValueError: 0.13417985135 is not in list

Maintenant, je sais que je pourrais simplement faire défiler la liste et comparer chaque élément pour voir s'il est <(min + 0.0000000000001) et> (min - 0.0000000000001), mais c'est un peu compliqué. Existe-t-il un moyen plus élégant (de préférence intégré) de trouver l'index du plus petit élément dans une liste de flottants?

39
thornate

Vous parcourez efficacement la liste une fois pour trouver la valeur minimale, puis la parcourez à nouveau pour trouver l'index, vous pouvez faire les deux en une seule fois:

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

J'utiliserais:

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

Alors val sera la valeur minimale et idx sera son index.

67
David Wolever

Utilisation de la méthode argmin pour les tableaux numpy.

import numpy as np
np.argmin(myList)

Cependant, ce n'est pas la méthode la plus rapide: elle est 3 fois plus lente que la réponse d'OP sur mon ordinateur. C'est peut-être le plus concis.

21
AlexP

Je pense que cela vaut la peine de mettre quelques horaires ici pour une certaine perspective.

Tous les timings effectués sur OS-X 10.5.8 avec python2.7

Réponse de John Clement:

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    

Réponse de David Wolever:

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

Réponse de l'OP:

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

Notez que je place délibérément le plus petit élément en dernier dans la liste pour faire .index aussi lent que possible. Il serait intéressant de voir à quel N l'itération une fois que les réponses deviendraient compétitives avec l'itération deux fois que nous avons ici.

Bien sûr, la vitesse n'est pas tout et la plupart du temps, cela ne vaut même pas la peine de s'inquiéter ... choisissez celui qui est le plus facile à lire, sauf s'il s'agit d'un goulot d'étranglement dans les performances de votre code (puis profil sur vos données typiques du monde réel - de préférence sur vos machines cibles).

13
mgilson