4421 votes

Trouver l'indice d'un élément dans une liste

Étant donné une liste ["foo", "bar", "baz"] et un élément de la liste "bar" Comment obtenir son index ? 1 ?

16 votes

Est-ce que vous renvoyez : [1] L'indice le plus bas au cas où il y a plusieurs instances de "bar" , [2] Tous les indices de "bar" ?

8 votes

A) Est-il garanti que l'élément est dans la liste, ou sinon comment devons-nous gérer le cas d'erreur ? (return None/ raise ValueError) b) Est-il garanti que les entrées de la liste sont uniques, et devons-nous retourner le premier indice d'une correspondance, ou tous les indices ?

1 votes

Voir les réponses avec l'intégration de numpy, les tableaux numpy sont beaucoup plus efficaces que les listes Python. Si la liste est courte, il n'y a aucun problème à en faire une copie à partir d'une liste Python, si elle ne l'est pas, vous devriez peut-être envisager de stocker les éléments dans un tableau numpy en premier lieu.

6029voto

Alex Coventry Points 11090
>>> ["foo", "bar", "baz"].index("bar")
1

Référence : Structures de données > Plus sur les listes

Les mises en garde suivantes

Notez que même si c'est peut-être la façon la plus propre de répondre à la question comme demandé , index est une composante plutôt faible de la list API, et je ne me souviens pas de la dernière fois où je l'ai utilisé en colère. On m'a fait remarquer dans les commentaires que, comme cette réponse est fortement référencée, elle devrait être plus complète. Quelques mises en garde concernant list.index suivre. Cela vaut probablement la peine de jeter un coup d'œil à la documentation correspondante :

list.index(x[, start[, end]])

Retourne l'indice basé sur zéro dans la liste du premier élément dont la valeur est égale à x . Lève un ValueError s'il n'existe pas d'élément de ce type.

Les arguments facultatifs commencer y fin sont interprétés comme dans le notation des tranches et sont utilisés pour limiter la recherche à une sous-séquence particulière de la liste. L'indice retourné est calculé par rapport au début de la séquence complète plutôt que par rapport à l'argument start.

Complexité temporelle linéaire en fonction de la longueur de la liste

Un site index vérifie chaque élément de la liste dans l'ordre, jusqu'à ce qu'il trouve une correspondance. Si votre liste est longue et que vous ne savez pas à peu près où se trouve la correspondance dans la liste, cette recherche peut devenir un goulot d'étranglement. Dans ce cas, vous devez envisager une structure de données différente. Notez que si vous savez à peu près où trouver la correspondance, vous pouvez donner à la fonction index un indice. Par exemple, dans cet extrait, l.index(999_999, 999_990, 1_000_000) est environ cinq ordres de grandeur plus rapide que le droit l.index(999_999) car le premier ne doit chercher que 10 entrées, alors que le second en cherche un million :

>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514

Renvoie uniquement l'indice de l'élément premier match à son argument

Un appel à index recherche dans la liste dans l'ordre jusqu'à ce qu'il trouve une correspondance, et s'arrête là. Si vous prévoyez d'avoir besoin d'indices pour un plus grand nombre de correspondances, vous devez utiliser une liste de compréhension ou une expression génératrice.

>>> [1, 1].index(1)
0
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> next(g)
0
>>> next(g)
2

La plupart des endroits où j'aurais autrefois utilisé index J'utilise maintenant une compréhension de liste ou une expression de générateur parce qu'elles sont plus généralisables. Donc si vous envisagez d'utiliser index , jetez un coup d'œil à ces excellentes fonctionnalités de Python.

Déclenche une erreur si l'élément n'est pas présent dans la liste

Un appel à index donne lieu à un ValueError si l'élément n'est pas présent.

>>> [1, 1].index(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 2 is not in list

Si l'élément n'est pas présent dans la liste, vous devez soit

  1. Vérifiez-le d'abord avec item in my_list (approche propre et lisible), ou
  2. Enveloppez le index appeler dans un try/except qui attrape ValueError (probablement plus rapide, du moins lorsque la liste à rechercher est longue, et que l'élément est généralement présent).

46 votes

Index renvoie le premier élément dont la valeur est "bar". Si "bar" existe deux fois dans la liste, vous ne trouverez jamais la clé pour le deuxième "bar". Voir la documentation : docs.python.org/3/tutorial/datastructures.html

12 votes

Si vous ne recherchez qu'un seul élément (le premier), j'ai trouvé que index() est un peu moins de 90% plus rapide que la compréhension de liste contre des listes d'entiers.

2 votes

Quelle structure de données doit être utilisée si la liste est très longue ?

987voto

davidavr Points 6670

Une chose qui est vraiment utile pour apprendre Python est d'utiliser la fonction d'aide interactive :

>>> help(["foo", "bar", "baz"])
Help on list object:

class list(object)
 ...

 |
 |  index(...)
 |      L.index(value, [start, [stop]]) -> integer -- return first index of value
 |

qui vous mènera souvent à la méthode que vous recherchez.

11 votes

bpython est un moyen agréable et convivial de lire les documents de manière interactive.

19 votes

@davidavr oui, mais alors le reste d'entre nous qui veut juste le googler au lieu de faire défiler les documents d'aide n'aurait pas ce bel ensemble central et classé d'options. :)

716voto

Haidro Points 24336

La majorité des réponses expliquent comment trouver un seul indice mais leurs méthodes ne renvoient pas d'index multiples si l'élément figure plusieurs fois dans la liste. Utilisez enumerate() :

for i, j in enumerate(['foo', 'bar', 'baz']):
    if j == 'bar':
        print(i)

El index() ne renvoie que la première occurrence, tandis que la fonction enumerate() renvoie toutes les occurrences.

Comme une compréhension de la liste :

[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']

Voici également une autre petite solution avec itertools.count() (ce qui est à peu près la même approche que pour enumerate) :

from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']

Cette méthode est plus efficace pour les grandes listes que l'utilisation de enumerate() :

$ python -m timeit -s "from itertools import izip as zip, count" "[i for i, j in zip(count(), ['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 174 usec per loop
$ python -m timeit "[i for i, j in enumerate(['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 196 usec per loop

3 votes

L'énumération fonctionne mieux que les méthodes basées sur l'index pour moi, puisque je cherche à rassembler les indices des chaînes de caractères en utilisant "startswith", et j'ai besoin de rassembler plusieurs occurrences. Ou existe-t-il une façon d'utiliser l'index avec "startswith" que je n'ai pas trouvée ?

9 votes

Dans mes mains, la version énumérée est toujours légèrement plus rapide. Certains détails d'implémentation peuvent avoir changé depuis que la mesure ci-dessus a été postée.

4 votes

La réponse à cette question date déjà de 2011 : stackoverflow.com/questions/6294179/

242voto

FMc Points 22663

Pour obtenir tous les index :

indexes = [i for i,x in enumerate(xs) if x == 'foo']

7 votes

Il existe déjà une autre question à ce sujet, ajoutée en 2011 : stackoverflow.com/questions/6294179/

158voto

Hongbo Zhu Points 1223

index() renvoie le premièrement indice de valeur !

| index(...)
| L.index(valeur, [start, [stop]]) -> integer -- retourne le premier index de la valeur

def all_indices(value, qlist):
    indices = []
    idx = -1
    while True:
        try:
            idx = qlist.index(value, idx+1)
            indices.append(idx)
        except ValueError:
            break
    return indices

all_indices("foo", ["foo","bar","baz","foo"])

3 votes

Et si elle n'existe pas dans la liste ?

1 votes

Un élément inexistant entraînera une ValueError.

1 votes

Cette réponse conviendrait mieux ici : stackoverflow.com/questions/6294179/

Prograide.com

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.

Powered by:

X