![](/img/trans.png)
[英]In Python, how do you find the index of the first value greater than a threshold in a sorted list?
[英]Python: index of fist element smaller than threshold in reverse sorted list
類似的問題在這里被要求排序列表,但解決方案使用了bisect
,它不適用於保留排序列表。
假設我有一個列表,按相反順序排序,鍵入中間元素,
my_list = [[3,0.99,1], [2,0.98,54], [10,.85,4], [1,0.7,10], [12,0.69,31], [12,0.65,43], [1.56,0] ....]
我想在中間元素上應用一系列閾值,例如,在單獨的排序列表中
threshold = [0.97, 0.90, 0.83, 0.6]
我試圖找出小於閾值的第一個元素的索引。 在上面的例子中它應該返回,
index_list = [2, 2, 3, 6]
建議如何以最快的方式完成?
根據@ gnibbler的這個好答案 ,你可以自己重寫bisect
代碼以滿足你的需要
我稍微修改了@ gnibbler中的代碼,以便它可以在你的情況下使用
優化是因為您的閾值也是排序的,我們不需要每次搜索整個列表,而是從最后的結果索引開始
def reverse_binary_search(a, x, lo=0, hi=None):
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)/2
if x > a[mid][4]:
hi = mid
else:
lo = mid+1
return lo
my_list = [[3,0.99,1], [2,0.98,54], [10,.85,4], [1,0.7,10], [12,0.69,31], [12,0.65,43], [1.56,0]]
threshold = [0.97, 0.90, 0.83, 0.6]
index_list = []
last_index = 0
for t in threshold:
last_index = reverse_binary_search(my_list, t, last_index) # next time start search from last_index
index_list.append(last_index)
感謝@ PhilCooper提出的寶貴建議。 以下是他提出的使用生成器的代碼:
def reverse_binary_search(a, threshold):
lo = 0
for t in threshold:
if lo < 0:
raise ValueError('lo must be non-negative')
hi = len(a)
while lo < hi:
mid = (lo+hi)/2
if t > a[mid][6]:
hi = mid
else:
lo = mid+1
yield lo
my_list = [[3,0.99,1], [2,0.98,54], [10,.85,4], [1,0.7,10], [12,0.69,31], [12,0.65,43], [1.56,0]]
threshold = [0.97, 0.90, 0.83, 0.6]
index_list = list(reverse_binary_search(my_list, threshold))
使用numpy,我認為它看起來比純python實現更清晰,並且幾乎肯定會更快:
import numpy as np
arr = np.array([[3,0.99,1], [2,0.98,54], [10,.85,4], [1,0.7,10], [12,0.69,31], [12,0.65,43], [10,0.50, 24]])
thresholds = [0.97, 0.90, 0.83, 0.60]
idx = [np.min(np.where(arr[:,1] < i)) for i in thresholds if np.where(arr[:,1] < i)[0].size > 0]
print idx
[2, 2, 3, 6]
請嘗試以下方法:
threshold = [0.97, 0.90, 0.83, 0.6]
my_list = [[3,0.99,1], [2,0.98,54], [10,.85,4], [1,0.7,10], [12,0.69,31], [12,0.65,43], [1,.56,0]]
threshold = [0.97, 0.90, 0.83, 0.6]
index_list = []
ti = 0
for i, item in enumerate(my_list):
if item[1] >= threshold[ti]:
continue
while ti < len(threshold) and item[1] < threshold[ti]:
index_list.append(i)
ti += 1
我在想你應該得到鑰匙並反轉。 然后bisecet沒問題
from bisect import bisect_left
keys = [vals[1] for vals in my_list]
keys.reverse()
mylen = len(my_list)
[mylen-bisect_left(keys,t) for t in threshold]
如果你已經numpy:
my_array = np.array([[3,0.99,1], [2,0.98,54], [10,.85,4], [1,0.7,10], [12,0.69,31], [12,0.65,43], [10,0.50, 24]])
thresholds = [0.97, 0.90, 0.83, 0.60]
my_array.shape[0]-arr[::-1,1].searchsorted(threshold)
import bisect
my_list_2 = sorted(my_list, key=lambda x:x[1])
for x in threshold:
len(my_list) - bisect.bisect([z[1] for z in my_list_2], x)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.