Каким будет самый питонический способ найти первый индекс в списке, который больше x?
Например, с
list = [0.5, 0.3, 0.9, 0.8]
Функция
f(list, 0.7)
вернется
2.
Каким будет самый питонический способ найти первый индекс в списке, который больше x?
Например, с
list = [0.5, 0.3, 0.9, 0.8]
Функция
f(list, 0.7)
вернется
2.
2
потому что 0.9 > 0.7
или потому что 0.8 > 0.7
? Другими словами, вы ищите последовательно или в порядке возрастания значений?
Ответы:
next(x[0] for x in enumerate(L) if x[1] > 0.7)
next()
, может быть, это для удобочитаемости:next(i for i,v in enumerate(L) if v > 0.7)
itertools.chain()
вместо добавления таких списков.
next((i for i, x in enumerate(L) if x > value), -1)
если список отсортирован, то bisect.bisect_left(alist, value)
для большого списка быстрее, чем next(i for i, x in enumerate(alist) if x >= value)
.
bisect_left
равно O (log n), а listcomp - O (n), т. е. чем больше n
, тем больше преимуществ на bisect_left()
стороне. Я пытался найти индекс 500_000
в range(10**6)
использовании bisect_left()
-> 3,75 микросекунды и используя genexpr с next()
-> 51,0 миллисекунды [ 10_000
раз] медленнее , как ожидалось.
filter(lambda x: x>.7, seq)[0]
bisect_left()
(самый быстрый) и 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
. Использование index = next[ n for n,i in enumerate(alist) if i>0.7 ]
ошибки дает: NameError: name 'index' is not defined
. next
немного быстрее: разница во времени составляет 12,7 нс против 11,9 нс для 60 000 номеров.
for index, elem in enumerate(elements):
if elem > reference:
return index
raise ValueError("Nothing Found")
1) NUMPY ARGWHERE, общие списки
Если вам нравится использовать numpy, то в общих списках (отсортированных или несортированных) будет работать следующее:
numpy.argwhere(np.array(searchlist)>x)[0]
или если вам нужен ответ в виде списка:
numpy.argwhere(np.array(searchlist)>x).tolist()[0]
или если вам нужен ответ в виде целочисленного индекса:
numpy.argwhere(np.array(searchlist)>x).tolist()[0][0]
2) СОРТИРОВАТЬСЯ по ЧИСЛАМ, отсортированные списки (очень эффективны для поиска в списках)
Однако, если ваш список поиска отсортирован, гораздо чище и приятнее использовать функцию np.searchsorted :
numpy.searchsorted(searchlist,x)
Приятная вещь в использовании этой функции заключается в том, что помимо поиска единственного значения x, x также может быть списком, т.е. вы также можете вернуть список индексов для списка найденных значений [x1, x2, x3 .. xn ] ( и в данном случае это очень эффективно по сравнению с пониманием списка ).
У меня была аналогичная проблема, когда мой список был очень длинным. решения на основе понимания или фильтрации пройдут через весь список. itertools.takewhile прервет цикл, как только условие станет ложным в первый раз:
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)
Я знаю, что ответов уже много, но иногда мне кажется, что слово pythonic переводится как «однострочный».
Когда я думаю, что лучшее определение ближе к этому ответу :
«Использование возможностей языка Python для создания ясного, лаконичного и поддерживаемого кода».
Хотя некоторые из приведенных выше ответов являются краткими, я не считаю их ясными, и программисту-новичку потребуется время, чтобы понять, что не делает их чрезвычайно удобными в обслуживании для команды, состоящей из многих уровней навыков.
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)
или же
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)
Я думаю, что вышеизложенное легко понять новичку и все еще достаточно кратко, чтобы быть принятым любым опытным программистом на Python.
Я считаю, что написание глупого кода - это хорошо.
>>> 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
Вы также можете сделать это, используя numpy
:
import numpy as np
list(np.array(SearchList) > x).index(True)
Попробуй это:
def Renumerate(l):
return [(len(l) - x, y) for x,y in enumerate(l)]
пример кода:
Renumerate(range(10))
вывод:
(10, 0)
(9, 1)
(8, 2)
(7, 3)
(6, 4)
(5, 5)
(4, 6)
(3, 7)
(2, 8)
(1, 9)