簡體   English   中英

從排序列表中獲取大於給定數字的第一個元素

[英]Get first element greater than a given number from a sorted list

我有兩個清單。 列表B就像一個數據庫,我需要逐個比較列表A的每個元素。 讓我們說

B = [0.6, 1.7, 3, 4.5]
A = [0.6, 0.9, 1.2, 1.5, 2, 2.5, 3, 4, 4.5]

B是一個排序列表,因此對於每個A [i],只要算法在B中找到一個> = A [i]的數字,它就應該將其作為輸出返回。 所以我的輸出應該類似於:

C = [0.6, 1.7, 1.7, 1.7, 3, 3, 3, 4.5, 4.5]

能否請您建議最簡單的解決方案,盡可能避免嵌套循環?

如果你可以使用第三方庫,一個解決方案是NumPy通過np.searchsorted

import numpy as np

B = np.array([0.6, 1.7, 3, 4.5])
A = [0.6, 0.9, 1.2, 1.5, 2, 2.5, 3, 4, 4.5]

res = B[np.searchsorted(B, A)]

array([ 0.6,  1.7,  1.7,  1.7,  3. ,  3. ,  3. ,  4.5,  4.5])

這將比順序循環或基於標准庫中的bisect的算法更有效。

只是next會做( 如果我理解正確的話 ):

A = [0.6, 0.9, 1.2, 1.5, 2, 2.5, 3, 4, 4.5]
B = [0.6, 1.7, 3, 4.5]

C = [next(b for b in B if b >= a) for a in A]

print(C)  # -> [0.6, 1.7, 1.7, 1.7, 3, 3, 3, 4.5, 4.5]

由於B已排序,您可以使用bisect二進制搜索B的正確值:

>>> B = [0.6, 1.7, 3, 4.5]
>>> A = [0.6, 0.9, 1.2, 1.5, 2, 2.5, 3, 4, 4.5]
>>> import bisect
>>> [B[bisect.bisect_left(B, a)] for a in A]
[0.6, 1.7, 1.7, 1.7, 3, 3, 3, 4.5, 4.5]

這具有復雜度O(alogb)ab分別是AB長度。 假設A也被排序,如在您的示例中,您也可以在O(a+b)

i, C = 0, []
for a in A:
    while B[i] < a:
        i += 1
    C.append(B[i])

但請注意,如果A包含的數字大於B任何數字,則兩種方法(以及到目前為止發布的其他答案)都將失敗。

由於您的給定B列表已排序,您可以使用:

B = [0.6, 1.7, 3, 4.5]
A = [0.6, 0.9, 1.2, 1.5, 2, 2.5, 3, 4, 4.5]

def first_greater_elem(lst, elem):
    for item in lst:
       if item >= elem:
         return item

然后只使用列表理解

C = [first_greater_elem(B,item) for item in A ]

產量

[0.6, 1.7, 1.7, 1.7, 3, 3, 3, 4.5, 4.5]

另一種方法可能是使用bisect包中的bisect_left方法。

C = [B[bisect_left(B,item)] for item in A ]

產量

[0.6, 1.7, 1.7, 1.7, 3, 3, 3, 4.5, 4.5]

如果list_a包含大於list_b的數字遞歸方式(對原始列表具有破壞性) 也有效

def pick(lst, ref, res=None):
  if res == None: res = []
  if len(lst) == 0: return res
  if ref[0] >= lst[0]:
    res.append(ref[0])
    lst.pop(0)
  elif len(ref) == 1 and ref[0] < lst[0]:
    # res.extend(lst) # if want to append the rest of lst instead of stop the loop
    # or do whathever is best for you
    return res
  else: ref.pop(0)
  pick(lst, ref, res)
  return res


list_b = [0.6, 1.7, 3, 3.9]
list_bb = [0.5]
list_a = [0.6, 0.9, 1.2, 1.5, 2, 2.5, 3, 4, 4.5]

print(pick(list_a, list_b))
#=> [0.6, 1.7, 1.7, 1.7, 3, 3, 3]

print(pick(list_a, list_bb))
#=> []

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM