listas - Encontrar el índice de un elemento dado una lista que lo contiene en Python




recorrer agregar (23)

Para aquellos que vienen de otro idioma como yo, tal vez con un simple bucle sea 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 Entonces, ¿qué hace exactamente enumerar? . Eso me ayudó a entender.

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


Y ahora para algo completamente diferente...

... como confirmar la existencia del elemento 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 cuerdas 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]
>>> 

Actualizar

Después de otro año de desarrollo de python cara a cara, mi respuesta original me da un poco de vergüenza, por lo que para aclarar las cosas, uno puede usar el código anterior; sin embargo, la forma mucho más idiomática de obtener el mismo comportamiento sería utilizar la comprensión de 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 sugirió en su respuesta anterior . En el momento en que respondí originalmente esta pregunta, ni siquiera vi esa respuesta porque no la entendí. Espero que mi ejemplo un poco más detallado ayude a la comprensión.

Si la línea de código que aparece arriba todavía no tiene sentido para usted, le recomiendo encarecidamente la "comprensión de la lista de python" de Google y dedique unos minutos a familiarizarse. Es solo una de las muchas funciones poderosas que hacen que sea un placer usar Python para desarrollar código.


Según lo indicado por @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

Encontrar índices de observaciones múltiples:

list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]

Prueba varios 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 via more_itertools .


Encontrar el índice de un elemento dado 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, seguro, 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ás un ValueError
  • Si hay más de uno de los valores en la lista, solo obtendrá el índice del primero.

Sin valores

Si el valor puede faltar, debe capturar el ValueError .

Puedes 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 tendrá una verificación de si el valor devuelto is o is not Ninguno:

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 incidencias, no obtendrá información completa con list.index :

>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar')              # nothing at index 3?
1

Podrías 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 incidencias, puede verificarlo con una verificación booleana del resultado, o simplemente no hacer nada si repite los resultados:

indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
    do_something(index)

Mejores datos de munging con pandas.

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

>>> 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 booleanos a la serie a través de la notación de subíndices, y obtendrá solo los miembros correspondientes:

>>> series[series == 'bar']
1    bar
3    bar
dtype: object

Si solo desea los índices, el atributo de índice 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í, podría usar una lista de comprensión con enumeración también, 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 ?

El problema XY está preguntando 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í, capturar el ValueError es bastante detallado, y prefiero evitarlo.

Por lo general, estoy iterando sobre la lista, así que generalmente mantendré un puntero a cualquier información interesante, obteniendo el índice con enumerar.

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

No recuerdo haber necesitado list.index , yo mismo. Sin embargo, he revisado la biblioteca estándar de Python y veo algunos usos excelentes para ella.

Hay muchos, muchos usos para ello en idlelib , para GUI y análisis de texto.

El módulo de keyword utiliza para encontrar marcadores de comentarios en el módulo para regenerar automáticamente la lista de palabras clave en él mediante metaprogramación.

En Lib / buzon.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 ser usado para obtener el próximo mes:

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

En Lib / tarfile.py similar a distutils para obtener una porción de 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 O (n) para list.index ), y se utilizan principalmente en el análisis (y la interfaz de usuario en el caso de Ocioso).

Si bien existen casos de uso para ello, son bastante infrecuentes. Si busca 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.


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. Utilice enumerate() :

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

La función index() 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 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

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

a = ["foo","bar","baz",'bar','any','much']

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

Si el desempeño es preocupante:

Se menciona en numerosas respuestas que el método list.index(item) del método list.index(item) 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 elementos de í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]

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

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

Hagamos nuestra función de encontrar índice.

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]

Sencillo

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

Salida:

0
4

index() devuelve el primer índice de valor!

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

Encontrando el índice del artículo x en la lista L :

idx = L.index(x) if (x in L) else -1

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, legible.


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]

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 usted desea?


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

Una variante en la respuesta de FMc y user7177 dará un dictado 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 un trazador de líneas para obtener todos los índices para una sola entrada. No hay garantías de eficiencia, aunque sí utilicé set (a) para reducir el número de veces que se llama a la lambda.


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 cuenta si la cadena no está en la lista también, si no está en la lista, entonces la ubicación = -1


Como las listas de Python están basadas en cero, podemos usar la función incorporada de 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 ítem a buscar.

(Nota: aquí estamos iterando usando i para obtener los índices, pero si necesitamos centrarnos en los elementos, podemos cambiar a j).


Para obtener todos los índices:

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

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


Hay dos posibilidades si la lista no tiene elementos repetidos que necesita para verificar el índice

 eg: li=[10,20,30] # here need to get index of 20 means
     li.index(20) # will work properly because 20 is not repeated

Si es repetido significa que solo te dará el primer índice.

Si necesita obtener todo el índice donde está presente el artículo significa

eg: li=[10,20,30,20,40, 50, 10] # here need to get index of 20 means its have 2 index (1,3) 

para conseguir eso necesitas hacerlo como

 li=[10,20,30,20,40, 50, 10]
 [i for i, e in enumerate(li) if e == 20]

entonces obtendrás una lista de índice como o / p like [1,3]


Todos los índices con la función zip :

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

Cuenta de todos los elementos con itertools.groupby()

Una posibilidad adicional para obtener el recuento de todos los elementos de la lista podría ser mediante itertools.groupby() .

Con cuentas "duplicadas"

from itertools import groupby

L = ['a', 'a', 'a', 't', 'q', 'a', 'd', 'a', 'd', 'c']  # Input list

counts = [(i, len(list(c))) for i,c in groupby(L)]      # Create value-count pairs as list of tuples 
print(counts)

Devoluciones

[('a', 3), ('t', 1), ('q', 1), ('a', 1), ('d', 1), ('a', 1), ('d', 1), ('c', 1)]

Observe cómo combinó las primeras tres a 's como el primer grupo, mientras que otros grupos de a están presentes más abajo en la lista. Esto sucede porque la lista de entrada L no estaba ordenada. Esto puede ser un beneficio a veces si los grupos deberían estar separados.

Con cuentas únicas.

Si se desean conteos de grupos únicos, simplemente ordene la lista de entrada:

counts = [(i, len(list(c))) for i,c in groupby(sorted(L))]
print(counts)

Devoluciones

[('a', 5), ('c', 1), ('d', 2), ('q', 1), ('t', 1)]




python list