Y a-t-il des méthodes intégrées qui font partie des listes qui me donneraient le premier et le dernier indice d'une valeur, comme:
verts.IndexOf(12.345)
verts.LastIndexOf(12.345)
Y a-t-il des méthodes intégrées qui font partie des listes qui me donneraient le premier et le dernier indice d'une valeur, comme:
verts.IndexOf(12.345)
verts.LastIndexOf(12.345)
Btw verts[::-1] inverse simplement la liste, non ? Donc je dois compenser pour l'index, non ?
Peut-être les deux façons les plus efficaces de trouver le dernier index:
def rindex(lst, value):
lst.reverse()
i = lst.index(value)
lst.reverse()
return len(lst) - i - 1
def rindex(lst, value):
return len(lst) - operator.indexOf(reversed(lst), value) - 1
Les deux ne prennent que O(1) d'espace supplémentaire et les deux inversions sur place de la première solution sont beaucoup plus rapides que de créer une copie inversée. Comparons cela avec les autres solutions postées précédemment:
def rindex(lst, value):
return len(lst) - lst[::-1].index(value) - 1
def rindex(lst, value):
return len(lst) - next(i for i, val in enumerate(reversed(lst)) if val == value) - 1
Résultats des tests, mes solutions sont les rouges et vertes:
Ceci est pour rechercher un chiffre dans une liste d'un million de chiffres. L'axe des x représente l'emplacement de l'élément recherché : 0% signifie qu'il est au début de la liste, 100% signifie qu'il est à la fin de la liste. Toutes les solutions sont les plus rapides à l'emplacement 100%, avec les deux solutions reversed
prenant à peu près aucun temps pour cela, la solution double-inversion prenant un peu de temps, et la copie inversée prenant beaucoup de temps.
Un regard plus attentif sur l'extrémité droite:
À l'emplacement 100%, la solution de copie inversée et la solution de double inversion passent tout leur temps sur les inversions (index()
est instantané), donc nous voyons que les deux inversions sur place sont environ sept fois plus rapides que la création de la copie inversée.
Ce qui précède était avec lst = list(range(1_000_000, 2_000_001))
, ce qui crée pratiquement les objets int séquentiellement en mémoire, ce qui est extrêmement favorable au cache. Refaisons-le après avoir mélangé la liste avec random.shuffle(lst)
(probablement moins réaliste, mais intéressant):
Tout a beaucoup ralenti, comme prévu. La solution de copie inversée est celle qui souffre le plus, à 100% elle prend maintenant environ 32 fois (!) plus de temps que la solution de double inversion. Et la solution avec enumerate
est désormais la deuxième plus rapide seulement après l'emplacement 98%.
En général, j'aime la solution avec operator.indexOf
le mieux, car c'est la plus rapide pour la dernière moitié ou le dernier quart de tous les emplacements, qui sont peut-être les emplacements les plus intéressants si vous utilisez réellement rindex
pour quelque chose. Et ce n'est que légèrement plus lent que la solution de double inversion dans les premiers emplacements.
Tous les tests effectués avec CPython 3.9.0 64 bits sur Windows 10 Pro 1903 64 bits.
Les listes Python disposent de la méthode index()
, que vous pouvez utiliser pour trouver la position de la première occurrence d'un élément dans une liste. Notez que list.index()
déclenche une erreur ValueError
lorsque l'élément n'est pas présent dans la liste, vous devrez donc l'encadrer dans un bloc try
/except
:
try:
idx = lst.index(value)
except ValueError:
idx = None
Pour trouver la position de la dernière occurrence d'un élément dans une liste de manière efficace (c'est-à-dire sans créer de liste intermédiaire inversée), vous pouvez utiliser cette fonction :
def rindex(lst, value):
for i, v in enumerate(reversed(lst)):
if v == value:
return len(lst) - i - 1 # retourne l'index dans la liste originale
return None
print(rindex([1, 2, 3], 3)) # 2
print(rindex([3, 2, 1, 3], 3)) # 3
print(rindex([3, 2, 1, 3], 4)) # None
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
2 votes
Je les lis aussi, mais ne rien savoir du python rend les choses plus difficiles. Je trouve sa syntaxe très cryptique.
0 votes
Si vos listes sont triées, alors vous voudrez peut-être consulter le module bisect <docs.python.org/3/library/bisect.html>.
0 votes
Voir la brillante réponse de Dikei ici en utilisant les fonctions intégrées enumerate et reversed : stackoverflow.com/questions/9836425/…