¿Cuál sería la forma más pitónica de encontrar el primer índice en una lista que sea mayor que x?
Por ejemplo, con
list = [0.5, 0.3, 0.9, 0.8]
La función
f(list, 0.7)
volvería
2.
¿Cuál sería la forma más pitónica de encontrar el primer índice en una lista que sea mayor que x?
Por ejemplo, con
list = [0.5, 0.3, 0.9, 0.8]
La función
f(list, 0.7)
volvería
2.
2
porque 0.9 > 0.7
o porque 0.8 > 0.7
? En otras palabras, ¿está buscando secuencialmente o en el orden de valores crecientes?
Respuestas:
next(x[0] for x in enumerate(L) if x[1] > 0.7)
next()
, pero tal vez esto por legibilidad:next(i for i,v in enumerate(L) if v > 0.7)
itertools.chain()
lugar de agregar listas como esta.
next((i for i, x in enumerate(L) if x > value), -1)
si la lista está ordenada, entonces bisect.bisect_left(alist, value)
es más rápido para una lista grande quenext(i for i, x in enumerate(alist) if x >= value)
.
bisect_left
es O (log n), mientras que listcomp es O (n), es decir, cuanto mayor sea, mayor será n
la ventaja del bisect_left()
lado. Intenté encontrar el índice de 500_000
al range(10**6)
usar bisect_left()
-> 3.75 microsegundos y usar genexpr con next()
-> 51.0 milisegundos [ 10_000
veces] más lento como se esperaba.
filter(lambda x: x>.7, seq)[0]
bisect_left()
(el más rápido) y enumerate()
.
>>> alist= [0.5, 0.3, 0.9, 0.8]
>>> [ n for n,i in enumerate(alist) if i>0.7 ][0]
2
IndexError: list index out of range
. El uso index = next[ n for n,i in enumerate(alist) if i>0.7 ]
de error da: NameError: name 'index' is not defined
. next
es ligeramente más rápido: la diferencia de tiempo es de 12,7 ns frente a 11,9 ns para 60 000 números.
for index, elem in enumerate(elements):
if elem > reference:
return index
raise ValueError("Nothing Found")
1) NUMPY ARGWHERE, listas generales
Si está contento de usar numpy, lo siguiente funcionará en listas generales (ordenadas o sin clasificar):
numpy.argwhere(np.array(searchlist)>x)[0]
o si necesita la respuesta en forma de lista:
numpy.argwhere(np.array(searchlist)>x).tolist()[0]
o si necesita la respuesta como un índice entero:
numpy.argwhere(np.array(searchlist)>x).tolist()[0][0]
2) NUMPY BÚSQUEDA CLASIFICADA, listas ordenadas (muy eficiente para buscar listas)
Sin embargo, si su lista de búsqueda está ordenada, es mucho más limpio y agradable usar la función np.searchsorted :
numpy.searchsorted(searchlist,x)
Lo bueno de usar esta función es que además de buscar un único valor x, x también puede ser una lista, es decir, también puede devolver una lista de índices para una lista de valores buscados [x1, x2, x3 .. xn ], ( y es muy eficiente en relación con la comprensión de una lista en este caso ).
Tuve un problema similar cuando mi lista era muy larga. la comprensión o las soluciones basadas en filtros pasarían por la lista completa. itertools.take while romperá el ciclo una vez que la condición se vuelva falsa la primera vez:
from itertools import takewhile
def f(l, b): return len([x for x in takewhile(lambda x: x[1] <= b, enumerate(l))])
l = [0.5, 0.3, 0.9, 0.8]
f(l, 0.7)
Sé que ya hay muchas respuestas, pero a veces siento que la palabra pythonic se traduce en 'una sola línea'.
Cuando creo que una mejor definición está más cerca de esta respuesta :
"Aprovechar las características del lenguaje Python para producir código claro, conciso y fácil de mantener".
Si bien algunas de las respuestas anteriores son concisas, no las encuentro claras y un programador novato tardaría un tiempo en comprenderlas, por lo que no las hace extremadamente fáciles de mantener para un equipo formado por muchos niveles de habilidad.
l = [0.5, 0.3, 0.9, 0.8]
def f(l, x):
for i in l:
if i >x: break
return l.index(i)
f(l,.7)
o
l = [0.5, 0.3, 0.9, 0.8]
def f(l, x):
for i in l:
if i >x: return l.index(i)
f(l,.7)
Creo que lo anterior es fácil de entender por un novato y aún es lo suficientemente conciso como para ser aceptado por cualquier programador de Python veterano.
Creo que escribir código tonto es positivo.
>>> f=lambda seq, m: [ii for ii in xrange(0, len(seq)) if seq[ii] > m][0]
>>> f([.5, .3, .9, .8], 0.7)
2
También puede hacer esto usando numpy
:
import numpy as np
list(np.array(SearchList) > x).index(True)
Prueba este:
def Renumerate(l):
return [(len(l) - x, y) for x,y in enumerate(l)]
código de ejemplo:
Renumerate(range(10))
salida:
(10, 0)
(9, 1)
(8, 2)
(7, 3)
(6, 4)
(5, 5)
(4, 6)
(3, 7)
(2, 8)
(1, 9)