Dada una lista ["foo", "bar", "baz"]
y un elemento en la lista "bar"
, ¿cómo obtengo su index ( 1
) en Python?
Dada una lista ["foo", "bar", "baz"]
y un elemento en la lista "bar"
, ¿cómo obtengo su index ( 1
) en Python?
Respuestas:
>>> ["foo", "bar", "baz"].index("bar")
1
Referencia: Estructuras de datos> Más sobre listas
Tenga en cuenta que si bien esta es quizás la forma más limpia de responder a la pregunta que se le hizo , index
es un componente bastante débil de la list
API, y no puedo recordar la última vez que lo usé con ira. Se me ha señalado en los comentarios que debido a que esta respuesta está muy referenciada, debería hacerse más completa. Algunas advertencias sobre list.index
seguir. Probablemente valga la pena echarle un vistazo a la documentación:
list.index(x[, start[, end]])
Devuelve el índice basado en cero en la lista del primer elemento cuyo valor es igual a x . Aumenta un
ValueError
si no hay tal artículo.Los argumentos opcionales start y end se interpretan como en la notación de corte y se usan para limitar la búsqueda a una subsecuencia particular de la lista. El índice devuelto se calcula en relación con el comienzo de la secuencia completa en lugar del argumento de inicio.
Una index
llamada verifica cada elemento de la lista en orden, hasta que encuentra una coincidencia. Si su lista es larga y no sabe aproximadamente en qué parte de la lista ocurre, esta búsqueda podría convertirse en un cuello de botella. En ese caso, debe considerar una estructura de datos diferente. Tenga en cuenta que si sabe aproximadamente dónde encontrar la coincidencia, puede dar index
una pista. Por ejemplo, en este fragmento, l.index(999_999, 999_990, 1_000_000)
es aproximadamente cinco órdenes de magnitud más rápido que directo l.index(999_999)
, porque el primero solo tiene que buscar 10 entradas, mientras que el segundo busca un millón:
>>> 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
Una llamada para index
buscar en la lista en orden hasta que encuentre una coincidencia y se detiene allí. Si espera necesitar índices de más coincidencias, debe utilizar una lista de comprensión o expresión generadora.
>>> [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
En la mayoría de los lugares donde alguna vez lo hubiera usado index
, ahora uso una lista de comprensión o expresión generadora porque son más generalizables. Entonces, si está considerando alcanzarlo index
, eche un vistazo a estas excelentes características de Python.
Una llamada a index
resulta en un ValueError
si el elemento no está presente.
>>> [1, 1].index(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 2 is not in list
Si el elemento puede no estar presente en la lista, debe
item in my_list
(enfoque limpio y legible), oindex
llamada en un try/except
bloque que atrapa ValueError
(probablemente más rápido, al menos cuando la lista para buscar es larga y el elemento generalmente está presente).index()
es un 90% más rápido que la comprensión de listas con listas de enteros.
Una cosa que es realmente útil para aprender Python es usar la función de ayuda interactiva:
>>> help(["foo", "bar", "baz"])
Help on list object:
class list(object)
...
|
| index(...)
| L.index(value, [start, [stop]]) -> integer -- return first index of value
|
que a menudo lo llevará al método que está buscando.
La mayoría de las respuestas explican cómo encontrar un índice único , pero sus métodos no devuelven índices múltiples si el elemento está en la lista varias veces. Uso enumerate()
:
for i, j in enumerate(['foo', 'bar', 'baz']):
if j == 'bar':
print(i)
La index()
función solo devuelve la primera aparición, mientras queenumerate()
devuelve todas las ocurrencias.
Como una lista de comprensión:
[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']
Aquí también hay otra pequeña solución con itertools.count()
(que es más o menos el mismo enfoque que enumerar):
from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']
Esto es más eficiente para listas más grandes que usar 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
Para obtener todos los índices:
indexes = [i for i,x in enumerate(xs) if x == 'foo']
index()
devuelve el primer índice de valor!
El | índice (...)
| L.index (valor, [inicio, [detener]]) -> entero - devuelve el primer índice de valor
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"])
Surgirá un problema si el elemento no está en la lista. Esta función maneja el problema:
# 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']
Debe establecer una condición para verificar si el elemento que está buscando está en la lista
if 'your_element' in mylist:
print mylist.index('your_element')
else:
print None
Todas las funciones propuestas aquí reproducen el comportamiento inherente del lenguaje pero ocultan lo que está sucediendo.
[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
¿Por qué escribir una función con manejo de excepciones si el lenguaje proporciona los métodos para hacer lo que quieres?
Si desea todos los índices, puede usar 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),)
Es una solución clara y legible.
Encontrar el índice de un elemento dada una lista que lo contiene en Python
Para una lista
["foo", "bar", "baz"]
y un elemento en la lista"bar"
, ¿cuál es la forma más limpia de obtener su índice (1) en Python?
Bueno, claro, está el método de índice, que devuelve el índice de la primera aparición:
>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1
Hay un par de problemas con este método:
ValueError
Si el valor puede faltar, debe capturar el ValueError
.
Puede hacerlo con una definición reutilizable como esta:
def index(a_list, value):
try:
return a_list.index(value)
except ValueError:
return None
Y úsalo así:
>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1
Y la desventaja de esto es que probablemente verifique si el valor devuelto is
o is not
Ninguno:
result = index(a_list, value)
if result is not None:
do_something(result)
Si pudiera tener más casos, no obtendrá información completa con list.index
:
>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar') # nothing at index 3?
1
Puede enumerar en una lista la comprensión de los índices:
>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]
Si no tiene ocurrencias, puede verificarlo con una verificación booleana del resultado, o simplemente no hacer nada si recorre los resultados:
indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
do_something(index)
Si tiene pandas, puede obtener fácilmente esta información con un objeto Serie:
>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0 foo
1 bar
2 baz
3 bar
dtype: object
Una verificación de comparación devolverá una serie de booleanos:
>>> series == 'bar'
0 False
1 True
2 False
3 True
dtype: bool
Pase esa serie de booleanos a la serie mediante notación de subíndice, y obtendrá solo los miembros coincidentes:
>>> series[series == 'bar']
1 bar
3 bar
dtype: object
Si solo desea los índices, el atributo index devuelve una serie de enteros:
>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')
Y si los quiere en una lista o tupla, simplemente páselos al constructor:
>>> list(series[series == 'bar'].index)
[1, 3]
Sí, también podría usar una comprensión de lista con enumerate, pero eso no es tan elegante, en mi opinión: está haciendo pruebas de igualdad en Python, en lugar de dejar que el código incorporado escrito en C lo maneje:
>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]
El problema XY es preguntar acerca de su intento de solución en lugar de su problema real.
¿Por qué crees que necesitas el índice dado un elemento en una lista?
Si ya conoce el valor, ¿por qué le importa dónde está en una lista?
Si el valor no está allí, la captura ValueError
es bastante detallada, y prefiero evitar eso.
Por lo general, estoy iterando sobre la lista de todos modos, por lo que generalmente mantendré un puntero a cualquier información interesante, obteniendo el índice con enumerate.
Si está mezclando datos, probablemente debería usar pandas, que tiene herramientas mucho más elegantes que las soluciones puras de Python que he mostrado.
No recuerdo haberlo necesitado list.index
. Sin embargo, he examinado la biblioteca estándar de Python y veo algunos usos excelentes para ella.
Hay muchos, muchos usos para ello idlelib
, para GUI y análisis de texto.
El keyword
módulo lo utiliza para buscar marcadores de comentarios en el módulo para regenerar automáticamente la lista de palabras clave a través de metaprogramación.
En Lib / box.py parece estar usándolo como una asignación ordenada:
key_list[key_list.index(old)] = new
y
del key_list[key_list.index(key)]
En Lib / http / cookiejar.py, parece usarse para obtener el próximo mes:
mon = MONTHS_LOWER.index(mon.lower())+1
En Lib / tarfile.py similar a distutils para obtener un corte hasta un elemento:
members = members[:members.index(tarinfo)]
En Lib / pickletools.py:
numtopop = before.index(markobject)
Lo que estos usos parecen tener en común es que parecen operar en listas de tamaños restringidos (importante debido al tiempo de búsqueda de O (n) para list.index
), y se usan principalmente en el análisis (y la IU en el caso de Idle).
Si bien hay casos de uso, son bastante poco comunes. Si se encuentra buscando esta respuesta, pregúntese si lo que está haciendo es el uso más directo de las herramientas proporcionadas por el idioma para su caso de uso.
Todos los índices con la zip
función:
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')
Con enumerate (alist) puede almacenar el primer elemento (n) que es el índice de la lista cuando el elemento x es igual a lo que busca.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Esta función toma el elemento y la lista como argumentos y devuelve la posición del elemento en la lista, como vimos antes.
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"))
Salida
[1, 3, 5, 7]
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Salida:
0
4
Otra opción
>>> 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]
>>>
... como confirmar la existencia del artículo antes de obtener el índice. Lo bueno de este enfoque es que la función siempre devuelve una lista de índices, incluso si es una lista vacía. Funciona con cadenas también.
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')
Cuando se pega en una ventana interactiva de Python:
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]
>>>
Después de otro año de desarrollo de Python, estoy un poco avergonzado por mi respuesta original, por lo que para dejar las cosas claras, uno ciertamente puede usar el código anterior; sin embargo, la forma mucho más idiomática de obtener el mismo comportamiento sería usar la comprensión de la lista, junto con la función enumerate ().
Algo como esto:
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')
Que, cuando se pega en una ventana interactiva de Python produce:
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]
>>>
Y ahora, después de revisar esta pregunta y todas las respuestas, me doy cuenta de que esto es exactamente lo que FMc sugirió en su respuesta anterior . En el momento en que originalmente respondí esta pregunta, ni siquiera vi esa respuesta, porque no la entendí. Espero que mi ejemplo un poco más detallado ayude a comprender.
Si la única línea de código anterior aún no tiene sentido para usted, le recomiendo encarecidamente la 'comprensión de la lista de python' de Google y tome unos minutos para familiarizarse. Es solo una de las muchas características poderosas que hacen que sea un placer usar Python para desarrollar código.
Una variante en la respuesta de FMc y user7177 dará un dict que puede devolver todos los índices para cualquier entrada:
>>> 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]}
>>>
También puede usar esto como una línea para obtener todos los índices para una sola entrada. No hay garantías de eficiencia, aunque utilicé el set (a) para reducir la cantidad de veces que se llama al lambda.
Encontrar el índice del elemento x en la lista L:
idx = L.index(x) if (x in L) else -1
Como las listas de Python están basadas en cero, podemos usar la función integrada zip de la siguiente manera:
>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]
donde "pajar" es la lista en cuestión y "aguja" es el elemento a buscar.
(Nota: Aquí estamos iterando usando i para obtener los índices, pero si necesitamos centrarnos en los elementos, podemos cambiar a 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)
Esto explica si la cadena no está en la lista también, si no está en la lista, entonces location = -1
El index()
método Python arroja un error si no se encontró el elemento. Por lo tanto, puede hacerlo similar a la indexOf()
función de JavaScript que se devuelve -1
si no se encuentra el elemento:
try:
index = array.index('search_keyword')
except ValueError:
index = -1
Hay una respuesta más funcional a esto.
list(filter(lambda x: x[1]=="bar",enumerate(["foo", "bar", "baz", "bar", "baz", "bar", "a", "b", "c"])))
Forma más genérica:
def get_index_of(lst, element):
return list(map(lambda x: x[0],\
(list(filter(lambda x: x[1]==element, enumerate(lst))))))
Scala
/ de programación funcionales entusiastas
Démosle el nombre lst
a la lista que tiene. Uno puede convertir la lista lst
a a numpy array
. Y luego use numpy.where para obtener el índice del elemento elegido en la lista. A continuación se detalla la forma en que lo implementará.
import numpy as np
lst = ["foo", "bar", "baz"] #lst: : 'list' data type
print np.where( np.array(lst) == 'bar')[0][0]
>>> 1
Para aquellos que vienen de otro idioma como yo, tal vez con un bucle simple es más fácil de entender y usar:
mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
if item == "bar":
print(index, item)
Estoy agradecido por ¿Qué hace exactamente enumerar? . Eso me ayudó a entender.
Si va a encontrar un índice una vez, entonces usar el método "index" está bien. Sin embargo, si va a buscar sus datos más de una vez, le recomiendo usar el módulo bisect . Tenga en cuenta que el uso de datos de módulo bisecado debe ordenarse. Entonces ordena los datos una vez y luego puede usar bisect. Usando bisectos módulo en mi máquina es aproximadamente 20 veces más rápido que usar el método index.
Aquí hay un ejemplo de código que usa Python 3.8 y la sintaxis anterior:
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}")
Salida:
t1=0.0400, t2=0.0020, diffs t1/t2=19.60
En numerosas respuestas se menciona que el método incorporado de list.index(item)
método es un algoritmo O (n). Está bien si necesita realizar esto una vez. Pero si necesita acceder a los índices de elementos varias veces, tiene más sentido crear primero un diccionario (O (n)) de pares de ítems-índice y luego acceder al índice en O (1) cada vez que lo necesite eso.
Si está seguro de que los elementos de su lista nunca se repiten, puede:
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 puede tener elementos duplicados y necesita devolver todos sus índices:
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]
Como lo indica @TerryA, muchas respuestas discuten cómo encontrar un índice.
more_itertools
es una biblioteca de terceros con herramientas para localizar múltiples índices dentro de un iterable.
Dado
import more_itertools as mit
iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]
Código
Encuentra índices de múltiples observaciones:
list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]
Prueba múltiples artículos:
list(mit.locate(iterable, lambda x: x in {"bar", "ham"}))
# [1, 3, 5]
Ver también más opciones con more_itertools.locate
. Instalar a través de > pip install more_itertools
.
usando el diccionario, donde procesa la lista primero y luego agrega el índice
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]
en mi opinión, ["foo", "bar", "baz"].index("bar")
es bueno, ¡pero no es suficiente! porque si "bar" no está en el diccionario, se ValueError
eleva . Entonces puede usar esta función:
def find_index(arr, name):
try:
return arr.index(name)
except ValueError:
return -1
if __name__ == '__main__':
print(find_index(["foo", "bar", "baz"], "bar"))
y el resultado es:
1
y si name no estaba en arr, la función return -1.por ejemplo:
print (find_index (["foo", "bar", "baz"], "fooo"))
-1
l = [1, 2]; find_index(l, 3)
regresaría -1
y l[find_index(l, 3)]
regresaría 2
. -1 es algo malo para devolver, solo devuelve None.
"bar"
, [2] Todos los índices de"bar"
?