Encontrar el índice de un elemento en una lista

3742

Dada una lista ["foo", "bar", "baz"]y un elemento en la lista "bar", ¿cómo obtengo su índice ( 1) en Python?

3
  • 6
    ¿Está devolviendo: [1] El índice más bajo en caso de que haya varias instancias de "bar", [2] Todos los índices de "bar"? 12 de mayo de 2018 a las 20:56
  • 4
    a) ¿Está garantizado que el elemento está en la lista o, de lo contrario, cómo debemos manejar el caso de error? (return None / raise ValueError) b) ¿Se garantiza que las entradas de la lista sean únicas, y deberíamos devolver el primer índice de una coincidencia, o todos los índices?
    smci
    21 de mayo de 2018 a las 6:20
  • Vea las respuestas con la integración de numpy, los arreglos de numpy son mucho más eficientes que las listas de Python. Si la lista es corta, no hay problema para hacer una copia de ella desde una lista de Python, si no lo es, quizás debería considerar almacenar los elementos en una matriz numpy en primer lugar. 28 de enero de 2020 a las 12:21
5210
>>> ["foo", "bar", "baz"].index("bar")
1

Referencia: Estructuras de datos> Más sobre listas

Siguen las advertencias

Tenga en cuenta que si bien esta es quizás la forma más limpia de responder a la pregunta tal como se hace , indexes un componente bastante débil de la listAPI, y no puedo recordar la última vez que lo usé con enojo. Se me ha señalado en los comentarios que debido a que esta respuesta está muy referenciada, debería ser más completa. Algunas advertencias a list.indexcontinuación. Probablemente valga la pena inicialmente echar un vistazo a la documentación:

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

Return zero-based index in the list of the first item whose value is equal to x. Raises a ValueError if there is no such item.

The optional arguments start and end are interpreted as in the slice notation and are used to limit the search to a particular subsequence of the list. The returned index is computed relative to the beginning of the full sequence rather than the start argument.

Complejidad de tiempo lineal en la longitud de la lista

Una indexllamada comprueba todos los elementos de la lista en orden, hasta que encuentra una coincidencia. Si su lista es larga y no sabe aproximadamente en qué lugar de la lista aparece, esta búsqueda podría convertirse en un cuello de botella. En ese caso, debería considerar una estructura de datos diferente. Tenga en cuenta que si sabe aproximadamente dónde encontrar la coincidencia, puede dar indexuna 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
 

Solo devuelve el índice de la primera coincidencia con su argumento

Una llamada a indexbusca en la lista en orden hasta que encuentra una coincidencia y se detiene allí. Si espera necesitar índices de más coincidencias, debe usar una comprensión de lista o una 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 usé index, ahora uso una expresión de comprensión de lista o generador porque son más generalizables. Entonces, si está considerando buscar index, eche un vistazo a estas excelentes características de Python.

Lanza si el elemento no está presente en la lista

Una llamada a indexda como resultado un ValueErrorsi 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 es posible que el elemento no esté presente en la lista, debe

  1. Compruébelo primero con item in my_list(enfoque limpio y legible), o
  2. Envuelva la indexllamada en un try/exceptbloque que capture ValueError(probablemente más rápido, al menos cuando la lista para buscar es larga y el elemento suele estar presente).
7
  • 30
    index devuelve el primer elemento cuyo valor es "bar". Si "barra" existe dos veces en la lista, nunca encontrará la clave para la segunda "barra". Ver documentación: docs.python.org/3/tutorial/datastructures.html 30 de enero de 2018 a las 4:51
  • 4
    Si solo está buscando un elemento (el primero), descubrí que index()es un 90% más rápido que la comprensión de listas contra listas de números enteros. 19/09/19 a las 20:13
  • ¿Qué estructura de datos debería usarse si la lista es muy larga? 22/02/20 a las 20:36
  • @izhang: Algún índice auxiliar, como un dict {element -> list_index}, si los elementos son hash y la posición en la lista es importante. 24 feb.20 a las 4:30
  • secuencia1 = ordenada (secuencia2, clave = .secuencia3.index) es un modismo muy útil. Puede usar el índice con más frecuencia si está en su repertorio. 24 de febrero a las 6:42
945

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 le llevará al método que está buscando.

2
  • 5
    bpython es una forma agradable y fácil de usar de leer los documentos de forma interactiva.
    goetzc
    22/09/19 a las 18:09
  • 7
    @davidavr sí, pero el resto de nosotros que solo queremos buscarlo en Google en lugar de desplazarnos por los documentos de ayuda no tendríamos este bonito conjunto de opciones centralizadas y clasificadas. :) 6 abr.20 a las 23:42
629

La mayoría de las respuestas explican cómo encontrar un único índice , pero sus métodos no devuelven varios índices si el elemento está en la lista varias veces. Utilizar 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 que enumerate()devuelve todas las apariciones.

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 prácticamente 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
4
  • 1
    La enumeración funciona mejor que los métodos basados ​​en índices para mí, ya que busco recopilar los índices de cadenas usando "startswith", y necesito recopilar varias ocurrencias. ¿O hay alguna forma de usar index with "startswith" que no pude entender 26 oct 2017 a las 19:15
  • 5
    En mis manos, la versión enumerada es consistentemente un poco más rápida. Es posible que algunos detalles de implementación hayan cambiado desde que se publicó la medición anterior. 17/11/2017 a las 18:43
  • 4
    Esto ya fue respondido desde '11: stackoverflow.com/questions/6294179/…
    Cristik
    10 feb 2019 a las 10:55
  • 1
    ¡Qué ahorrador de una respuesta! gracias !! .. Intenté durante 2 días obtener el índice de un diccionario anidado antes de entender que podíamos usar enumerate
    Viv
    31 jul.20 a las 16:48
201

Para obtener todos los índices:

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

index()devuelve el primer índice de valor!

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

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
93

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
0
92
a = ["foo","bar","baz",'bar','any','much']

indexes = [index for index in range(len(a)) if a[index] == 'bar']
1
64

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
5
  • 1
    ¡Esto nos ayuda a evitar intentar atrapar!
    devssh
    10 de septiembre de 2018 a las 7:45
  • 2
    Sin embargo, podría duplicar la complejidad. ¿Alguien lo comprobó? 6 de septiembre de 2019 a las 15:58
  • 1
    @stefanct La complejidad del tiempo sigue siendo lineal, pero recorrerá la lista dos veces. 28/01/20 a las 20:55
  • @ApproachingDarknessFish Eso es obviamente lo que quise decir. Incluso si es pedante el mismo orden de complejidad, iterar dos veces podría ser una gran desventaja en muchos casos de uso, así que lo mencioné. Y todavía no sabemos la respuesta ... 29 de enero de 2020 a las 1:50
  • @stefanct, esto probablemente duplica la complejidad, creo que el inoperador en una lista tiene un tiempo de ejecución lineal. @ApproachingDarknessFish declaró que iteraría dos veces, lo que responde a su pregunta, y tiene razón al decir que duplicar la complejidad lineal no es un gran problema. No llamaría iterar sobre una lista dos veces una desventaja severa en muchos casos de uso, ya que la teoría de la complejidad nos dice que O (n) + O (n) -> O (2 * n) -> O (n), es decir, el cambio suele ser insignificante. 27 de junio a las 6:48
51

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.

3
  • 5
    ¿Qué pasa con las listas de cadenas, listas de objetos no numéricos, etc.? 12/10/2016 a las 14:55
  • 2
    Esta respuesta debería publicarse mejor aquí: stackoverflow.com/questions/6294179/…
    Cristik
    10/02/19 a las 10:58
  • 1
    Este es el mejor que he leído. Las matrices numpy son mucho más eficientes que las listas de Python. Si la lista es corta, no hay problema para hacer una copia de ella desde una lista de Python, si no lo es, quizás el desarrollador debería considerar almacenar los elementos en una matriz numpy en primer lugar. 28 de enero de 2020 a las 12:23
48

Todas las funciones propuestas aquí reproducen el comportamiento inherente del lenguaje pero oscurecen 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 quiere por sí mismo?

2
  • 10
    El tercer método itera dos veces sobre la lista, ¿verdad? 5 de febrero de 2017 a las 13:59
  • Re: "Todas las funciones propuestas aquí" : en el momento de escribir este artículo, tal vez, pero debería comprobar las respuestas más recientes para ver si todavía es cierto. 4 de junio de 2018 a las 20:19
45

Finding the index of an item given a list containing it in Python

For a list ["foo", "bar", "baz"] and an item in the list "bar", what's the cleanest way to get its index (1) in 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:

  • si el valor no está en la lista, obtendrá un ValueError
  • si hay más de uno de los valores en la lista, solo obtiene el índice del primero

Sin valores

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 utilícelo así:

>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1

Y la desventaja de esto es que probablemente tendrá una verificación para ver si el valor devuelto iso is notNinguno:

result = index(a_list, value)
if result is not None:
    do_something(result)

Más de un valor en la lista

Si pudiera tener más ocurrencias, 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 de comprensión 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)

Mejor intercambio de datos con pandas

Si tiene pandas, puede obtener fácilmente esta información con un objeto Series:

>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0    foo
1    bar
2    baz
3    bar
dtype: object

Una comprobación de comparación devolverá una serie de valores booleanos:

>>> series == 'bar'
0    False
1     True
2    False
3     True
dtype: bool

Pase esa serie de valores booleanos a la serie a través de la 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 de índice devuelve una serie de números 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 lista de comprensión 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]

¿Es este un problema XY ?

The XY problem is asking about your attempted solution rather than your actual problem.

¿Por qué cree que necesita 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á ahí, detectarlo ValueErrores bastante detallado, y prefiero evitarlo.

Por lo general, estoy iterando sobre la lista de todos modos, por lo que generalmente mantengo un puntero a cualquier información interesante, obteniendo el índice con enumerate.

Si está manipulando datos, probablemente debería usar pandas, que tiene herramientas mucho más elegantes que las soluciones alternativas puras de Python que he mostrado.

No recuerdo list.indexhaberme necesitado a mí mismo. Sin embargo, he revisado la biblioteca estándar de Python y veo algunos usos excelentes para ella.

Hay muchos, muchos usos para él idlelib, para GUI y análisis de texto.

El keywordmódulo lo usa para encontrar marcadores de comentarios en el módulo para regenerar automáticamente la lista de palabras clave en él a través de la metaprogramación.

En Lib / mailbox.py parece estar usándolo como un mapeo ordenado:

key_list[key_list.index(old)] = new

y

del key_list[key_list.index(key)]

En Lib / http / cookiejar.py, parece que se usa para obtener el mes siguiente:

mon = MONTHS_LOWER.index(mon.lower())+1

En Lib / tarfile.py similar a distutils para obtener una porción de un artículo:

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) list.index), y se usan principalmente en el análisis (y la interfaz de usuario en el caso de inactivo).

Si bien existen casos de uso para ello, 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 lenguaje para su caso de uso.

26

Obtener todas las ocurrencias y la posición de uno o más elementos (idénticos) en una lista

Con enumerate (alist) puedes almacenar el primer elemento (n) que es el índice de la lista cuando el elemento x es igual a lo que buscas.

>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>

Hagamos nuestra función findindex

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"))

Producción


[1, 3, 5, 7]

Sencillo

for n, i in enumerate([1, 2, 3, 4, 1]):
    if i == 1:
        print(n)

Producción:

0
4
2
23

Todos los índices con la zipfunció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')
1
19

Simplemente puedes ir con

a = [['hand', 'head'], ['phone', 'wallet'], ['lost', 'stock']]
b = ['phone', 'lost']

res = [[x[0] for x in a].index(y) for y in b]
17

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]
>>> 
1
15

Y ahora para algo completamente diferente...

... 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. También funciona con cuerdas.

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]
>>> 

Actualizar

Después de otro año de desarrollo de Python de cabeza hacia abajo, estoy un poco avergonzado por mi respuesta original, así que para dejar las cosas claras, ciertamente se 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 listas, 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')

Lo cual, 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 sugirió FMc en su respuesta anterior . En el momento en que respondí originalmente a esta pregunta, ni siquiera vi esa respuesta, porque no la entendía. Espero que mi ejemplo algo más detallado ayude a la comprensión.

Si la única línea de código anterior todavía no tiene sentido para usted, le recomiendo encarecidamente que busque en Google la 'comprensión de la lista de Python' y tómese 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.

13

Una variante de 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 conjunto (a) para reducir la cantidad de veces que se llama a lambda.

1
12

Encontrar el índice del elemento x en la lista L:

idx = L.index(x) if (x in L) else -1
1
  • 5
    Esto itera la matriz dos veces, por lo que podría resultar en problemas de rendimiento para matrices grandes.
    Cristik
    10 feb 2019 a las 11:00
10

Esta solución no es tan poderosa como otras, pero si es un principiante y solo conoce los forbucles, aún es posible encontrar el primer índice de un elemento evitando el ValueError:

def find_element(p,t):
    i = 0
    for e in p:
        if e == t:
            return i
        else:
            i +=1
    return -1
0
6

El index()método Python arroja un error si no se encontró el elemento. Entonces, en su lugar, puede hacerlo similar a la indexOf()función de JavaScript que devuelve -1si no se encontró el elemento:

try:
    index = array.index('search_keyword')
except ValueError:
    index = -1
1
  • 7
    sin embargo, JavaScript tiene la filosofía de que los resultados extraños son mejores que los errores, por lo que tiene sentido devolver -1, pero en Python, puede dificultar la localización del error, ya que -1 devuelve un elemento del final de la lista. 29/10/19 a las 22:44
6
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 tiene en cuenta si la cadena no está en la lista también, si no está en la lista, entonces location = -1

5

Existe la posibilidad de que ese valor no esté presente, por lo que para evitar este ValueError, podemos verificar si realmente existe en la lista.

list =  ["foo", "bar", "baz"]

item_to_find = "foo"

if item_to_find in list:
      index = list.index(item_to_find)
      print("Index of the item is " + str(index))
else:
    print("That word does not exist") 
4

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))))))
2
  • 1
    Esta respuesta se siente como en casa para Scala/ entusiastas de la programación funcional 21/08/18 a las 5:13
  • Cuando solo se necesita un valor en una lista que tiene muchas coincidencias, este toma mucho tiempo.
    Caveman
    22/06/20 a las 16:12
4

Dado que 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 enfocarnos en los elementos, podemos cambiar a j).

1
  • 4
    [i para i, j en enumerate (pajar) si j == 'aguja'] es más compacto y legible, creo. 27/12/2017 a las 7:23
4

Por uno comparable

# Throws ValueError if nothing is found
some_list = ['foo', 'bar', 'baz'].index('baz')
# some_list == 2

Predicado personalizado

some_list = [item1, item2, item3]

# Throws StopIteration if nothing is found
# *unless* you provide a second parameter to `next`
index_of_value_you_like = next(
    i for i, item in enumerate(some_list)
    if item.matches_your_criteria())

Encontrar índice de todos los elementos por predicado

index_of_staff_members = [
    i for i, user in enumerate(users)
    if user.is_staff()]
2
  • idx = next((i for i, v in enumerate(ls) if v == chk), -1) para obtener un comportamiento similar a str.index (chk). 10/12/20 a las 10:42
  • @ tejasvi88 Decidió poner un poco de trabajo extra en la respuesta
    Caveman
    10/12/20 a las 11:45
3

Si va a encontrar un índice una vez, entonces está bien usar el método "índice". 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ódulos bisectados debe ordenarse. Así que clasifica los datos una vez y luego puede usar bisect. Usar el módulo bisect en mi máquina es aproximadamente 20 veces más rápido que usar el método de índice.

A continuación, se muestra un ejemplo de código que utiliza la sintaxis de Python 3.8 y superior:

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}")

Producción:

t1=0.0400, t2=0.0020, diffs t1/t2=19.60
2

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. Entonces, ¿qué hace exactamente enumerar? . Eso me ayudó a comprender.

2

Démosle el nombre lsta la lista que tienes. Se puede convertir la lista lsta numpy array. Y luego use numpy.where para obtener el índice del elemento elegido en la lista. A continuación se muestra 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
1
  • No funciona si el elemento es una instancia de una clase
    Caveman
    22/06/20 a las 16:11
1

Si el rendimiento es motivo de preocupación:

En numerosas respuestas se menciona que el método de list.index(item)método incorporado 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 índice de elemento 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 fácilmente:

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]
1

Simplemente usa la función Python array.index()y con un simple Try / Except devuelve la posición del registro si se encuentra en la lista y devuelve -1 si no se encuentra en la lista (como en JavaScript con la función indexOf()).

fruits = ['apple', 'banana', 'cherry']

try:
  pos = fruits.index("mango")
except:
  pos = -1

En este caso, "mango" no está presente en la lista, fruitspor lo que la posvariable es -1, si hubiera buscado "cereza", la posvariable sería 2.