Cách dễ hiểu nhất để tìm chỉ mục đầu tiên trong danh sách lớn hơn x là gì?
Ví dụ, với
list = [0.5, 0.3, 0.9, 0.8]
Chức năng
f(list, 0.7)
sẽ trở lại
2.
Cách dễ hiểu nhất để tìm chỉ mục đầu tiên trong danh sách lớn hơn x là gì?
Ví dụ, với
list = [0.5, 0.3, 0.9, 0.8]
Chức năng
f(list, 0.7)
sẽ trở lại
2.
2
bởi vì 0.9 > 0.7
hay bởi vì 0.8 > 0.7
? Nói cách khác, bạn đang tìm kiếm tuần tự hay theo thứ tự giá trị tăng dần?
Câu trả lời:
next(x[0] for x in enumerate(L) if x[1] > 0.7)
next()
, nhưng có thể điều này để dễ đọc:next(i for i,v in enumerate(L) if v > 0.7)
itertools.chain()
thay vì thêm danh sách như thế này.
next((i for i, x in enumerate(L) if x > value), -1)
nếu danh sách được sắp xếp thì bisect.bisect_left(alist, value)
nhanh hơn cho một danh sách lớn hơn next(i for i, x in enumerate(alist) if x >= value)
.
bisect_left
là O (log n), trong khi listcomp là O (n) tức là, càng lớn n
thì càng có nhiều lợi thế bisect_left()
. Tôi đã cố gắng tìm chỉ mục 500_000
trong range(10**6)
việc sử dụng bisect_left()
-> 3,75 micro giây và sử dụng genxpr với next()
-> 51,0 mili giây [ 10_000
lần] chậm hơn như mong đợi.
filter(lambda x: x>.7, seq)[0]
bisect_left()
(nhanh nhất) và 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
. Sử dụng index = next[ n for n,i in enumerate(alist) if i>0.7 ]
lỗi cho: NameError: name 'index' is not defined
. next
nhanh hơn một chút: Chênh lệch thời gian là 12,7 ns so với 11,9 ns cho 60 000 số.
for index, elem in enumerate(elements):
if elem > reference:
return index
raise ValueError("Nothing Found")
1) NUMPY ARGWHERE, danh sách chung
Nếu bạn hài lòng khi sử dụng numpy, thì những điều sau sẽ hoạt động trên các danh sách chung (được sắp xếp hoặc không được sắp xếp):
numpy.argwhere(np.array(searchlist)>x)[0]
hoặc nếu bạn cần câu trả lời dưới dạng danh sách:
numpy.argwhere(np.array(searchlist)>x).tolist()[0]
hoặc nếu bạn cần câu trả lời dưới dạng chỉ số số nguyên:
numpy.argwhere(np.array(searchlist)>x).tolist()[0][0]
2) NUMPY SEARCHSORTED, danh sách được sắp xếp (rất hiệu quả để tìm kiếm danh sách)
Tuy nhiên, nếu danh sách tìm kiếm của bạn được sắp xếp, thì việc sử dụng hàm np.searchsorted sẽ gọn gàng và đẹp hơn nhiều :
numpy.searchsorted(searchlist,x)
Điều thú vị khi sử dụng hàm này là cũng như tìm kiếm một giá trị duy nhất x, x cũng có thể là một danh sách, tức là bạn cũng có thể trả về một danh sách các chỉ số cho danh sách các giá trị được tìm kiếm [x1, x2, x3 .. xn ], ( và nó rất hiệu quả so với khả năng hiểu danh sách trong trường hợp này ).
Tôi đã gặp vấn đề tương tự khi danh sách của tôi rất dài. sự hiểu biết hoặc các giải pháp dựa trên bộ lọc sẽ đi qua toàn bộ danh sách. itertools.takeworthy sẽ phá vỡ vòng lặp khi điều kiện trở thành sai lần đầu tiên:
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)
Tôi biết đã có rất nhiều câu trả lời, nhưng đôi khi tôi cảm thấy rằng từ pythonic được dịch thành 'một lớp lót'.
Khi tôi nghĩ một định nghĩa tốt hơn gần với câu trả lời này hơn :
"Khai thác các tính năng của ngôn ngữ Python để tạo ra mã rõ ràng, ngắn gọn và dễ bảo trì."
Mặc dù một số câu trả lời ở trên là ngắn gọn nhưng tôi không thấy chúng rõ ràng và một lập trình viên mới sẽ mất một thời gian để hiểu, do đó không khiến chúng trở nên cực kỳ dễ bảo trì đối với một nhóm được xây dựng với nhiều cấp độ kỹ năng.
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)
hoặc là
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)
Tôi nghĩ rằng những điều trên có thể dễ dàng hiểu bởi một người mới và vẫn đủ ngắn gọn để được chấp nhận bởi bất kỳ lập trình viên python kỳ cựu nào.
Tôi nghĩ rằng viết mã ngu ngốc là một tích cực.
>>> 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
Bạn cũng có thể làm điều này bằng cách sử dụng numpy
:
import numpy as np
list(np.array(SearchList) > x).index(True)
Hãy thử cái này:
def Renumerate(l):
return [(len(l) - x, y) for x,y in enumerate(l)]
mã ví dụ:
Renumerate(range(10))
đầu ra:
(10, 0)
(9, 1)
(8, 2)
(7, 3)
(6, 4)
(5, 5)
(4, 6)
(3, 7)
(2, 8)
(1, 9)