Вопрос неоднозначный. Ответ: 2потому что 0.9 > 0.7или потому что 0.8 > 0.7? Другими словами, вы ищите последовательно или в порядке возрастания значений?
Хороший ответ - это было определенно в 5-6 раз быстрее для меня, используя небольшой отсортированный список из 4 элементов, но (не уверен, делаю ли я ошибку), но когда я использую timeit с длинным списком из 10000 элементов numpy array Я считаю, что это примерно в два раза медленнее, чем приведенный выше ответ на понимание списка, чему я был удивлен.
Адриан Томпкинс,
1
@AdrianTompkins: что-то не так с вашим тестом. 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раз] медленнее , как ожидалось.
-1: Хотя технически правильно, не используйте фильтр, где понимание списка более читабельно и более производительно
truppo
filter (lambda x: x [1]> .7, enumerate (seq)) [0] [0] - простой линейный поиск
lowtech
4
Фильтр @truppo в python 3 возвращает генератор, поэтому он должен быть не хуже, чем понимание списка? Также я считаю этот способ более читаемым, чем решение enumerate.
BubuIIC
Одна вещь, которая не нравится в этом, заключается в том, что вы попадаете в обработку исключений, если в seq нет элемента больше 0,7.
Брайан С.
Решение технически неверное. Автор вопроса задал вопрос, как найти индекс элемента в списке. Но это решение вместо этого возвращает запись. Eventmore в Python 3.8 он медленнее bisect_left()(самый быстрый) и enumerate().
Сергей Невмержицкий
16
>>> alist= [0.5, 0.3, 0.9, 0.8]
>>> [ n for n,i inenumerate(alist) if i>0.7 ][0]
2
он потерпит неудачу, если 'x' больше любого другого значения в списке
mshsayem
2
@mshsayem: В данном случае проблема не определена. Неудача может быть правильным поступком.
S.Lott
@ S.Loot: Хорошее замечание. В противном случае , если не в результатах списка в понятной ошибки при назначении этой переменной: 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 номеров.
Лев
11
for index, elem inenumerate(elements):
if elem > reference:
return index
raise ValueError("Nothing Found")
2) СОРТИРОВАТЬСЯ по ЧИСЛАМ, отсортированные списки (очень эффективны для поиска в списках)
Однако, если ваш список поиска отсортирован, гораздо чище и приятнее использовать функцию np.searchsorted :
numpy.searchsorted(searchlist,x)
Приятная вещь в использовании этой функции заключается в том, что помимо поиска единственного значения x, x также может быть списком, т.е. вы также можете вернуть список индексов для списка найденных значений [x1, x2, x3 .. xn ] ( и в данном случае это очень эффективно по сравнению с пониманием списка ).
У меня была аналогичная проблема, когда мой список был очень длинным. решения на основе понимания или фильтрации пройдут через весь список. itertools.takewhile прервет цикл, как только условие станет ложным в первый раз:
from itertools import takewhile
deff(l, b):returnlen([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)
почему вы просто не пишете def f (l, b): return len (list (takewhile (lambda x: x [1] <= b, enumerate (l))))?
Аво Асатрян
2
Я знаю, что ответов уже много, но иногда мне кажется, что слово pythonic переводится как «однострочный».
Когда я думаю, что лучшее определение ближе к этому ответу :
«Использование возможностей языка Python для создания ясного, лаконичного и поддерживаемого кода».
Хотя некоторые из приведенных выше ответов являются краткими, я не считаю их ясными, и программисту-новичку потребуется время, чтобы понять, что не делает их чрезвычайно удобными в обслуживании для команды, состоящей из многих уровней навыков.
l = [0.5, 0.3, 0.9, 0.8]
deff(l, x):for i in l:
if i >x: breakreturn l.index(i)
f(l,.7)
или же
l = [0.5, 0.3, 0.9, 0.8]
deff(l, x):for i in l:
if i >x: return l.index(i)
f(l,.7)
Я думаю, что вышеизложенное легко понять новичку и все еще достаточно кратко, чтобы быть принятым любым опытным программистом на Python.
Я считаю, что написание глупого кода - это хорошо.
Это выглядит довольно гладко. Но теоретически он пройдет по всему списку, а затем вернет первый результат (больше x), верно? Есть ли способ сделать тот, который остановится сразу после получения первого результата?
c00kiemonster
что не так с обходом всего списка? если первое значение больше 0,7 находится ближе к концу списка, это не имеет значения.
ghostdog74
3
Правда. Но в этом конкретном случае списки, в которых я собираюсь использовать эту функцию, довольно длинные, поэтому я бы предпочел, чтобы он прекратил обход, как только совпадение будет найдено ...
c00kiemonster
независимо от того, длинный он или нет, если первое значение является последним вторым элементом списка, вам все равно придется пройти весь список, чтобы добраться туда!
ghostdog74
4
@ ghostdog74: Да, но это не причина, чтобы все случаи были наихудшими.
UncleBens
0
Вы также можете сделать это, используя numpy:
import numpy as np
list(np.array(SearchList) > x).index(True)
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")
источник
Еще один:
map(lambda x: x>.7, seq).index(True)
источник
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 :
Приятная вещь в использовании этой функции заключается в том, что помимо поиска единственного значения 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)
источник