Étant donné une liste ["foo", "bar", "baz"]
et un élément de la liste "bar"
, comment puis-je obtenir son index ( 1
) en Python?
Étant donné une liste ["foo", "bar", "baz"]
et un élément de la liste "bar"
, comment puis-je obtenir son index ( 1
) en Python?
Réponses:
>>> ["foo", "bar", "baz"].index("bar")
1
Référence: Structures de données> Plus d'informations sur les listes
Notez que bien que ce soit peut-être le moyen le plus propre de répondre à la question posée , index
c'est un composant plutôt faible de l' list
API, et je ne me souviens pas de la dernière fois que je l'ai utilisé avec colère. On m'a fait remarquer dans les commentaires que, parce que cette réponse est fortement référencée, elle devrait être rendue plus complète. Quelques mises en garde à propos de list.index
suivre. Il vaut probablement la peine de jeter un coup d'œil à la documentation:
list.index(x[, start[, end]])
Retourne un index de base zéro dans la liste du premier élément dont la valeur est égale à x . Déclenche un
ValueError
s'il n'y en a pas.Les arguments facultatifs début et fin sont interprétés comme dans la notation de tranche et sont utilisés pour limiter la recherche à une sous-séquence particulière de la liste. L'index renvoyé est calculé par rapport au début de la séquence complète plutôt que par l'argument de début.
Un index
appel 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ù dans la liste elle se produit, cette recherche pourrait 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 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 droit l.index(999_999)
, car le premier n'a qu'à rechercher 10 entrées, tandis que le second en recherche 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
Un appel à index
recherche dans la liste dans l'ordre jusqu'à ce qu'il trouve une correspondance et s'arrête là. Si vous pensez avoir besoin d'index de correspondances supplémentaires, vous devez utiliser une compréhension de liste ou une expression de générateur.
>>> [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 utilisé une fois index
, j'utilise maintenant une compréhension de liste ou une expression de générateur car ils sont plus généralisables. Donc, si vous envisagez d'atteindre index
, jetez un œil à ces excellentes fonctionnalités Python.
Un appel à index
entraîne 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 peut-être pas présent dans la liste, vous devez soit
item in my_list
(approche claire et lisible), ouindex
appel dans un try/except
bloc qui prend ValueError
(probablement plus rapide, au moins lorsque la liste à rechercher est longue et que l'élément est généralement présent.)index()
c'est un peu moins de 90% plus rapide que la compréhension de liste par rapport aux listes d'entiers.
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
|
ce qui vous mènera souvent à la méthode que vous recherchez.
La majorité des réponses expliquent comment trouver un seul index , mais leurs méthodes ne renvoient pas plusieurs index si l'élément figure plusieurs fois dans la liste. Utilisation enumerate()
:
for i, j in enumerate(['foo', 'bar', 'baz']):
if j == 'bar':
print(i)
La index()
fonction ne renvoie que la première occurrence, tandis qu'elle enumerate()
renvoie toutes les occurrences.
En tant que compréhension de liste:
[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']
Voici également une autre petite solution avec itertools.count()
(qui est à peu près la même approche que celle énumérée):
from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']
C'est plus efficace pour des listes plus grandes que d'utiliser 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
Pour obtenir tous les index:
indexes = [i for i,x in enumerate(xs) if x == 'foo']
index()
renvoie le premier indice de valeur!
| index (...)
| L.index (value, [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"])
Un problème surviendra si l'élément n'est pas dans la liste. Cette fonction gère le problème:
# if element is found it returns index of element else returns None
def find_element_in_list(element, list_element):
try:
index_element = list_element.index(element)
return index_element
except ValueError:
return None
a = ["foo","bar","baz",'bar','any','much']
indexes = [index for index in range(len(a)) if a[index] == 'bar']
Vous devez définir une condition pour vérifier si l'élément que vous recherchez est dans la liste
if 'your_element' in mylist:
print mylist.index('your_element')
else:
print None
Toutes les fonctions proposées ici reproduisent le comportement du langage inhérent mais obscurcissent ce qui se passe.
[i for i in range(len(mylist)) if mylist[i]==myterm] # get the indices
[each for each in mylist if each==myterm] # get the items
mylist.index(myterm) if myterm in mylist else None # get the first index and fail quietly
Pourquoi écrire une fonction avec gestion des exceptions si le langage fournit les méthodes pour faire ce que vous voulez lui-même?
Si vous voulez tous les index, vous pouvez utiliser NumPy :
import numpy as np
array = [1, 2, 1, 3, 4, 5, 1]
item = 1
np_array = np.array(array)
item_index = np.where(np_array==item)
print item_index
# Out: (array([0, 2, 6], dtype=int64),)
C'est une solution claire et lisible.
Trouver l'index d'un élément à partir d'une liste le contenant en Python
Pour une liste
["foo", "bar", "baz"]
et un élément de la liste"bar"
, quelle est la façon la plus propre d'obtenir son index (1) en Python?
Eh bien, bien sûr, il y a la méthode index, qui retourne l'index de la première occurrence:
>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1
Il y a quelques problèmes avec cette méthode:
ValueError
Si la valeur peut être manquante, vous devez attraper le ValueError
.
Vous pouvez le faire avec une définition réutilisable comme celle-ci:
def index(a_list, value):
try:
return a_list.index(value)
except ValueError:
return None
Et utilisez-le comme ceci:
>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1
Et l'inconvénient est que vous devrez probablement vérifier si la valeur retournée is
ou is not
Aucune:
result = index(a_list, value)
if result is not None:
do_something(result)
Si vous pouviez avoir plus d'occurrences, vous n'obtiendrez pas d' informations complètes avec list.index
:
>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar') # nothing at index 3?
1
Vous pouvez énumérer dans une liste la compréhension des index:
>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]
Si vous n'avez aucune occurrence, vous pouvez vérifier cela avec une vérification booléenne du résultat, ou tout simplement ne rien faire si vous parcourez les résultats:
indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
do_something(index)
Si vous avez des pandas, vous pouvez facilement obtenir ces informations avec un objet Series:
>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0 foo
1 bar
2 baz
3 bar
dtype: object
Une vérification de comparaison renverra une série de booléens:
>>> series == 'bar'
0 False
1 True
2 False
3 True
dtype: bool
Passez cette série de booléens à la série via la notation en indice, et vous obtenez uniquement les membres correspondants:
>>> series[series == 'bar']
1 bar
3 bar
dtype: object
Si vous voulez uniquement les index, l'attribut index renvoie une série d'entiers:
>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')
Et si vous les voulez dans une liste ou un tuple, passez-les simplement au constructeur:
>>> list(series[series == 'bar'].index)
[1, 3]
Oui, vous pouvez également utiliser une compréhension de liste avec énumération, mais ce n'est tout simplement pas aussi élégant, à mon avis - vous faites des tests d'égalité en Python, au lieu de laisser le code intégré écrit en C le gérer:
>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]
Le problème XY pose des questions sur votre tentative de solution plutôt que sur votre problème réel.
Pourquoi pensez-vous que vous avez besoin de l'index donné un élément dans une liste?
Si vous connaissez déjà la valeur, pourquoi vous souciez-vous de son emplacement dans une liste?
Si la valeur n'est pas là, la capture ValueError
est plutôt verbeuse - et je préfère éviter cela.
J'itère généralement sur la liste de toute façon, donc je garde généralement un pointeur sur toute information intéressante, obtenant l' index avec énumération.
Si vous mungingez des données, vous devriez probablement utiliser des pandas - qui ont des outils beaucoup plus élégants que les solutions de contournement Python que j'ai montrées.
Je ne me souviens pas avoir eu besoin de list.index
moi-même. Cependant, j'ai parcouru la bibliothèque standard de Python et je vois d'excellentes utilisations.
Il y a beaucoup, beaucoup d'utilisations pour idlelib
, dans l'interface graphique et l'analyse de texte.
Le keyword
module l'utilise pour trouver des marqueurs de commentaires dans le module pour régénérer automatiquement la liste de mots-clés qu'il contient via la métaprogrammation.
Dans Lib / mailbox.py, il semble l'utiliser comme un mappage ordonné:
key_list[key_list.index(old)] = new
et
del key_list[key_list.index(key)]
Dans Lib / http / cookiejar.py, semble être utilisé pour obtenir le mois prochain:
mon = MONTHS_LOWER.index(mon.lower())+1
Dans Lib / tarfile.py similaire à distutils pour obtenir une tranche jusqu'à un élément:
members = members[:members.index(tarinfo)]
Dans Lib / pickletools.py:
numtopop = before.index(markobject)
Ce que ces usages semblent avoir en commun, c'est qu'ils semblent fonctionner sur des listes de tailles limitées (important en raison du temps de recherche O (n) pour list.index
), et ils sont principalement utilisés dans l'analyse (et l'interface utilisateur dans le cas de l'inactivité).
Bien qu'il existe des cas d'utilisation pour cela, ils sont assez rares. Si vous cherchez cette réponse, demandez-vous si ce que vous faites est l'utilisation la plus directe des outils fournis par la langue pour votre cas d'utilisation.
Tous les index avec la zip
fonction:
get_indexes = lambda x, xs: [i for (y, i) in zip(xs, range(len(xs))) if x == y]
print get_indexes(2, [1, 2, 3, 4, 5, 6, 3, 2, 3, 2])
print get_indexes('f', 'xsfhhttytffsafweef')
Avec enumerate (alist), vous pouvez stocker le premier élément (n) qui est l'index de la liste lorsque l'élément x est égal à ce que vous recherchez.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Cette fonction prend l'élément et la liste comme arguments et renvoie la position de l'élément dans la liste, comme nous l'avons vu précédemment.
def indexlist(item2find, list_or_string):
"Returns all indexes of an item in a list or a string"
return [n for n,item in enumerate(list_or_string) if item==item2find]
print(indexlist("1", "010101010"))
Production
[1, 3, 5, 7]
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Production:
0
4
Une autre option
>>> a = ['red', 'blue', 'green', 'red']
>>> b = 'red'
>>> offset = 0;
>>> indices = list()
>>> for i in range(a.count(b)):
... indices.append(a.index(b,offset))
... offset = indices[-1]+1
...
>>> indices
[0, 3]
>>>
... comme confirmer l'existence de l'élément avant d'obtenir l'index. La bonne chose à propos de cette approche est que la fonction renvoie toujours une liste d'index - même s'il s'agit d'une liste vide. Cela fonctionne également avec les cordes.
def indices(l, val):
"""Always returns a list containing the indices of val in the_list"""
retval = []
last = 0
while val in l[last:]:
i = l[last:].index(val)
retval.append(last + i)
last += i + 1
return retval
l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')
Une fois collé dans une fenêtre python interactive:
Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def indices(the_list, val):
... """Always returns a list containing the indices of val in the_list"""
... retval = []
... last = 0
... while val in the_list[last:]:
... i = the_list[last:].index(val)
... retval.append(last + i)
... last += i + 1
... return retval
...
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>>
Après une autre année de développement tête baissée de python, je suis un peu gêné par ma réponse originale, donc pour remettre les pendules à l'heure, on peut certainement utiliser le code ci-dessus; cependant, la manière beaucoup plus idiomatique d'obtenir le même comportement serait d'utiliser la compréhension de liste, avec la fonction enumerate ().
Quelque chose comme ça:
def indices(l, val):
"""Always returns a list containing the indices of val in the_list"""
return [index for index, value in enumerate(l) if value == val]
l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')
Ce qui, une fois collé dans une fenêtre python interactive, donne:
Python 2.7.14 |Anaconda, Inc.| (default, Dec 7 2017, 11:07:58)
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def indices(l, val):
... """Always returns a list containing the indices of val in the_list"""
... return [index for index, value in enumerate(l) if value == val]
...
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>>
Et maintenant, après avoir examiné cette question et toutes les réponses, je me rends compte que c'est exactement ce que FMc a suggéré dans sa réponse précédente . Au moment où j'ai initialement répondu à cette question, je n'ai même pas vu cette réponse, car je ne la comprenais pas. J'espère que mon exemple un peu plus verbeux aidera à la compréhension.
Si la seule ligne de code ci-dessus n'a toujours pas de sens pour vous, je vous recommande fortement de comprendre la liste de python de Google et de prendre quelques minutes pour vous familiariser. Ce n'est qu'une des nombreuses fonctionnalités puissantes qui rendent l'utilisation de Python très agréable pour développer du code.
Une variante de la réponse de FMc et user7177 donnera un dict qui peut renvoyer tous les indices pour n'importe quelle entrée:
>>> a = ['foo','bar','baz','bar','any', 'foo', 'much']
>>> l = dict(zip(set(a), map(lambda y: [i for i,z in enumerate(a) if z is y ], set(a))))
>>> l['foo']
[0, 5]
>>> l ['much']
[6]
>>> l
{'baz': [2], 'foo': [0, 5], 'bar': [1, 3], 'any': [4], 'much': [6]}
>>>
Vous pouvez également l'utiliser comme une ligne pour obtenir tous les indices pour une seule entrée. Il n'y a aucune garantie d'efficacité, bien que j'aie utilisé set (a) pour réduire le nombre d'appels du lambda.
Cette solution n'est pas aussi puissante que les autres, mais si vous êtes débutant et ne connaissez que les for
boucles, il est toujours possible de trouver le premier index d'un élément tout en évitant la ValueError:
def find_element(p,t):
i = 0
for e in p:
if e == t:
return i
else:
i +=1
return -1
Recherche de l'index de l'élément x dans la liste L:
idx = L.index(x) if (x in L) else -1
Étant donné que les listes Python sont basées sur zéro, nous pouvons utiliser la fonction intégrée zip comme suit:
>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]
où "meule de foin" est la liste en question et "aiguille" est l'élément à rechercher.
(Remarque: Ici, nous itérons en utilisant i pour obtenir les index, mais si nous devons plutôt nous concentrer sur les éléments, nous pouvons passer à j.)
name ="bar"
list = [["foo", 1], ["bar", 2], ["baz", 3]]
new_list=[]
for item in list:
new_list.append(item[0])
print(new_list)
try:
location= new_list.index(name)
except:
location=-1
print (location)
Cela tient compte si la chaîne n'est pas dans la liste aussi, si elle n'est pas dans la liste alors location = -1
La index()
méthode Python génère une erreur si l'élément est introuvable. Donc, à la place, vous pouvez le rendre similaire à la indexOf()
fonction de JavaScript qui retourne -1
si l'article n'a pas été trouvé:
try:
index = array.index('search_keyword')
except ValueError:
index = -1
Il y a une réponse plus fonctionnelle à cela.
list(filter(lambda x: x[1]=="bar",enumerate(["foo", "bar", "baz", "bar", "baz", "bar", "a", "b", "c"])))
Forme plus générique:
def get_index_of(lst, element):
return list(map(lambda x: x[0],\
(list(filter(lambda x: x[1]==element, enumerate(lst))))))
Scala
/ fonctionnels programmation amateurs
Donnons le nom lst
à la liste que vous avez. On peut convertir la liste lst
en un numpy array
. Et, puis utilisez numpy.where pour obtenir l'index de l'élément choisi dans la liste. Voici comment vous allez l'implémenter.
import numpy as np
lst = ["foo", "bar", "baz"] #lst: : 'list' data type
print np.where( np.array(lst) == 'bar')[0][0]
>>> 1
Pour ceux qui viennent d'une autre langue comme moi, peut-être qu'avec une simple boucle c'est plus facile à comprendre et à utiliser:
mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
if item == "bar":
print(index, item)
Je suis reconnaissant pour Alors, que fait exactement l'énumération? . Cela m'a aidé à comprendre.
Si vous allez trouver un index une fois, alors utiliser la méthode "index" est très bien. Cependant, si vous allez rechercher vos données plus d'une fois, je vous recommande d'utiliser le module bissect . Gardez à l'esprit que l'utilisation des données du module bissect doit être triée. Vous triez donc les données une fois et vous pouvez ensuite utiliser la bissect. L'utilisation du module bissect sur ma machine est environ 20 fois plus rapide que l'utilisation de la méthode d'indexation.
Voici un exemple de code utilisant Python 3.8 et la syntaxe ci-dessus:
import bisect
from timeit import timeit
def bisect_search(container, value):
return (
index
if (index := bisect.bisect_left(container, value)) < len(container)
and container[index] == value else -1
)
data = list(range(1000))
# value to search
value = 666
# times to test
ttt = 1000
t1 = timeit(lambda: data.index(value), number=ttt)
t2 = timeit(lambda: bisect_search(data, value), number=ttt)
print(f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")
Production:
t1=0.0400, t2=0.0020, diffs t1/t2=19.60
Il est mentionné dans de nombreuses réponses que la méthode intégrée list.index(item)
est un algorithme O (n). C'est bien si vous devez effectuer cette opération une fois. Mais si vous devez accéder aux index des éléments un certain nombre de fois, il est plus logique de créer d'abord un dictionnaire (O (n)) de paires élément-index, puis d'accéder à l'index en O (1) chaque fois que vous en avez besoin. il.
Si vous êtes sûr que les éléments de votre liste ne sont jamais répétés, vous pouvez facilement:
myList = ["foo", "bar", "baz"]
# Create the dictionary
myDict = dict((e,i) for i,e in enumerate(myList))
# Lookup
myDict["bar"] # Returns 1
# myDict.get("blah") if you don't want an error to be raised if element not found.
Si vous pouvez avoir des éléments en double et devez renvoyer tous leurs indices:
from collections import defaultdict as dd
myList = ["foo", "bar", "bar", "baz", "foo"]
# Create the dictionary
myDict = dd(list)
for i,e in enumerate(myList):
myDict[e].append(i)
# Lookup
myDict["foo"] # Returns [0, 4]
Comme indiqué par @TerryA, de nombreuses réponses expliquent comment trouver un index.
more_itertools
est une bibliothèque tierce avec des outils pour localiser plusieurs index dans un itérable.
Donné
import more_itertools as mit
iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]
Code
Trouver des indices d'observations multiples:
list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]
Testez plusieurs éléments:
list(mit.locate(iterable, lambda x: x in {"bar", "ham"}))
# [1, 3, 5]
Voir aussi plus d'options avec more_itertools.locate
. Installez via > pip install more_itertools
.
en utilisant le dictionnaire, où traiter d'abord la liste, puis y ajouter l'index
from collections import defaultdict
index_dict = defaultdict(list)
word_list = ['foo','bar','baz','bar','any', 'foo', 'much']
for word_index in range(len(word_list)) :
index_dict[word_list[word_index]].append(word_index)
word_index_to_find = 'foo'
print(index_dict[word_index_to_find])
# output : [0, 5]
à mon avis, ["foo", "bar", "baz"].index("bar")
c'est bon mais ce n'est pas suffisant! car si "bar" n'est pas dans le dictionnaire, c'est ValueError
surélevé.
def find_index(arr, name):
try:
return arr.index(name)
except ValueError:
return -1
if __name__ == '__main__':
print(find_index(["foo", "bar", "baz"], "bar"))
et le résultat est:
1
et si le nom n'était pas à l'arr, la fonction retourne -1.par exemple:
print (find_index (["foo", "bar", "baz"], "fooo"))
-1
l = [1, 2]; find_index(l, 3)
reviendrait -1
et l[find_index(l, 3)]
reviendrait 2
. -1 est une mauvaise chose à retourner, renvoyez simplement None.
"bar"
, [2] Tous les indices de"bar"
?