recorrer - llenar una lista en python
Encontrar el índice de un elemento dado una lista que lo contiene en Python (27)
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.
Para una lista ["foo", "bar", "baz"]
y un elemento en la lista "bar"
, ¿cómo obtengo su índice (1) en Python?
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]
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.
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
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).
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
El método de index()
Python index()
emite un error si no se encontró el elemento, lo que apesta.
Entonces, en lugar de eso, puede hacerlo similar a la función indexOf()
de JavaScript que devuelve -1
si no se encontró el elemento:
try:
index = array.index(''search_keyword'')
except ValueError:
index = -1
Encontrando el índice del artículo x en la lista L :
idx = L.index(x) if (x in L) else -1
Esta solución no es tan poderosa como las otras, pero si usted es un principiante y solo conoce los bucles, todavía es posible encontrar el primer índice de un elemento y evitar el ValueError:
def find_element(p,t):
i = 0
for e in p:
if e == t:
return i
else:
i +=1
return -1
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]
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))))))
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
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]
>>>
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 obtener todos los índices:
indexes = [i for i,x in enumerate(xs) if x == ''foo'']
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 .
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]
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
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?
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'')
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.
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.
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"])
>>> ["foo", "bar", "baz"].index("bar")
1
Referencia: Estructuras de datos> Más en listas
Advertencias siguen
Tenga en cuenta que si bien esta es quizás la forma más limpia de responder la pregunta, el index
es un componente bastante débil de la list
API, y no puedo recordar la última vez que lo usé enojado. Se me indicó en los comentarios que, debido a que esta respuesta está muy referida, debería ser más completa. Algunas advertencias sobre list.index
siguen. Es probable que inicialmente valga la pena echarle un vistazo al docstring para ello:
>>> print(list.index.__doc__)
L.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.
Tiempo-complejidad lineal en longitud de lista
Una llamada de index
verifica 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, debe considerar una estructura de datos diferente. Tenga en cuenta que si sabe aproximadamente dónde encontrar la coincidencia, puede dar una pista al index
. 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 l.index(999_999)
directo l.index(999_999)
, porque el primero solo tiene que buscar 10 entradas, mientras que el último 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 a su argumento.
Una llamada para index
busca 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 lista de comprensión o expresión de generador.
>>> [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 mayoría de los lugares en los que alguna vez habría usado el index
, ahora uso una comprensión de lista o una expresión generadora porque son más generalizables. Entonces, si está considerando alcanzar el index
, eche un vistazo a estas excelentes características de Python.
Lanza si el elemento no está presente en la lista.
Una llamada para index
da como resultado 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, debería
- Verifíquelo primero con el
item in my_list
(enfoque limpio y legible), o - Envuelva la llamada de
index
en un bloquetry/except
que atrapaValueError
(probablemente más rápido, al menos cuando la lista de búsqueda es larga, y el elemento generalmente está presente).
a = ["foo","bar","baz",''bar'',''any'',''much'']
indexes = [index for index in range(len(a)) if a[index] == ''bar'']
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