[英]In Python, how do you find the index of the first value greater than a threshold in a sorted list?
[英]Python binary search-like function to find first number in sorted list greater than a specific value
我正在嘗試在Python中編寫一個函數,它找到排序列表中的第一個數字大於我作為參數傳遞的特定值。 我在網上找到了使用簡單列表推導來實現這一目的的例子,但出於我的目的,我需要經常在大型列表上執行此操作,因此在線性時間內運行的搜索過於昂貴。
雖然我遇到了一些無法正常工作的邊緣情況,但我在編寫迭代二進制搜索類函數時遇到了麻煩。 順便說一下,該功能不需要處理列表中沒有較大項目的情況。 這是我現有的功能:
def findFirstLarger(num, sortedList):
low = 0;
high = len(sortedList) - 1
mid = -1
while True:
print("low: " + str(low) + "\t high: " + str(high))
if (low > high):
print("Ah geez, low is " + str(low) + " and high is " + str(high))
return # debugging, don't want this to happen
if low == high:
return sortedList[low]
else:
mid = (low + high) / 2;
if num == sortedList[mid]:
return sortedList[mid]
elif num > sortedList[mid]:
low = mid + 1
else:
high = mid - 1
我注意到這個功能不起作用的一個案例如下:
>>> somenumbers=[n*2 for n in range(131072)]
>>> somenumbers[-5:]
[262134, 262136, 262138, 262140, 262142]
>>> binsearch.findFirstLarger(262139,somenumbers)
low: 0 high: 131071
low: 65536 high: 131071
low: 98304 high: 131071
low: 114688 high: 131071
low: 122880 high: 131071
low: 126976 high: 131071
low: 129024 high: 131071
low: 130048 high: 131071
low: 130560 high: 131071
low: 130816 high: 131071
low: 130944 high: 131071
low: 131008 high: 131071
low: 131040 high: 131071
low: 131056 high: 131071
low: 131064 high: 131071
low: 131068 high: 131071
low: 131070 high: 131071
low: 131070 high: 131069
Ah geez, low is 131070 and high is 131069
這里正確的結果是262140
,因為這是列表中第一個大於262139
。
任何人都可以推薦一個更實用的清潔實現嗎? 我不認為這會是一個如此深奧的問題,盡管我還沒有找到任何解決方案。
你試過bisect
模塊嗎?
def find_ge(a, key):
'''Find smallest item greater-than or equal to key.
Raise ValueError if no such item exists.
If multiple keys are equal, return the leftmost.
'''
i = bisect_left(a, key)
if i == len(a):
raise ValueError('No item found with key at or above: %r' % (key,))
return a[i]
find_ge(somenumbers, 262139)
您的代碼錯誤,(1) low > high
是有效的終止案例。 (2)你不應該停在low == high
,例如,當你的somenumbers
num == 3
為num == 3
時,它會返回一個不正確的索引。
如果您需要沒有bisect函數的實現,可以嘗試以下代碼:
def findFirstLargerOrEqual(num, sortedList):
'''Finds the smallest index in the sortedList
of the element which is greater-than or equal to num'''
slen = len(sortedList)
start = 0
while slen > 0:
m = start + slen//2
if sortedList[m] < num:
slen = slen - (m+1 - start)
start = m+1
continue
if start < m and sortedList[m-1] >= num:
slen = m - start
continue
return somenumbers[m]
raise ValueError('Not found')
somenumbers=[n*2 for n in range(131072)]
print(findFirstLargerOrEqual(262139, somenumbers)) #output: 262140
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.