2017-08-04 73 views
2

我有一個值列表,我需要給定任意任意起始索引,如果起始索引處的值爲零,則找到最接近的非零值。 ..從列表中獲得最接近的非零值的最佳方法

這是我有:

def getNearestNonZero(start_index): 
    mylist = [4,2,6,7,3,0,0,9,4,2,5,8,1,7] 
    val = mylist[start_index] 
    if val == 0: 
     loop_length = 0 
     after = mylist[start_index+1:] 
     before = mylist[:start_index] 
     before = before[::-1] 
     print(before, after) 

     if len(before) >= len(after): 
      loop_length = len(before) 
     else: 
      loop_length = len(after) 

     for i in range(loop_length): 
      if i < len(before): 
       before_val = before[i] 
      if i < len(after): 
       after_val = after[i] 

      if before_val > 0: 
       return before_val 

      if after_val > 0: 
       return after_val 

    return val 

result = getNearestNonZero(6) 
print(result) 

result = getNearestNonZero(5) 
print(result) 

[0,3,7,6,2,4] [9,4,2,5,8,1,7]

[3,7,6, 2,4] [0,9,4,2,5,8,1,7]

我做什麼,是我首先檢查以查看是否在start_index值爲>如果是,很好,請歸還。但是,如果該值是零,我們需要找到最接近的非零,與之前的偏愛,而不是之後......

要做到這一點,我分裂mylist成兩個單獨的列表,beforeafter。如果我的起始索引是6,before現在看起來像:[4,2,6,7,3,0],之後將如下所示:[9,4,2,5,8,1,7]

因爲我需要最接近的值到start_index,我扭轉我before名單:before = before[::-1]

然後我得到的最長的兩個(beforeafter)的長度。

然後我循環並檢查兩個列表中每個索引的值。第一個具有> 0的值被返回並且我的工作完成。

但是,這感覺非常笨重,好像它可以以更清潔的方式完成。

有沒有人有任何建議?給定一個起始索引,在列表中找到最接近的非零值的更快/更清潔/ pythonic方式是什麼?

+0

我投票在這裏結束這個問題,因爲它**已經轉載的代碼審查:https://codereview.stackexchange.com/questions/172113/best-way-to-get-nearest非零值從列表** –

回答

1

你可以先創建所有非零值的列表(以其索引一起)根據指數從start_index的距離做到這一點,然後排序此列表,並返回一個最接近:

def closest_nonzero(lst, start_index): 
    nonzeros = [(i, x) for i, x in enumerate(lst) if x != 0] 
    sorted_nonzeros = sorted(nonzeros, key=lambda x: abs(x[0] - start_index)) 
    return sorted_nonzeros[0][1] 

lst = [4,2,6,7,3,0,0,9,4,2,5,8,1,7] 
print(closest_nonzero(lst, 6)) # 9 
print(closest_nonzero(lst, 5)) # 3 
+0

你有我的upvote,但是這並沒有給價值之前prio,你有一些錯別字(功能名稱)。 +1 –

+0

修正了拼寫錯誤,但這實際上在給定'sorted'是一個穩定排序的值之前給了prio值,所以「之前的值」將會排在第一位。 –

+0

我試着用這個列表,你的函數仍然返回9,輸入6:lst = [4,2,6,7,3,0,0,0,9,4,2,5,8,1,7],你使用的第一個沒有prio命令 –

1

這裏有一個簡單的函數,它利用一些numpy函數返回最接近的非零值。

def closest_non_zero(l, i): 
    if l[i] > 0: 
     return l[i] 

    arr = np.array(l) 
    non_zeros = np.nonzero(arr)[0] 
    distances = np.abs(non_zeros - i) 
    closest_idx = np.min(np.where(distances == np.min(distances))) 

    return arr[non_zeros[closest_idx]] 
+0

不錯的解決方案與np(+1),但OP先要求值之前? –

0

我修改了Jonas Adler版本來考慮左邊的項目。儘管如此,他還是信任他。 (給元組添加一個值,如果離開,則爲正值,否則爲負值)。似乎工作。

def closest_nonzero(lst, start_index): 
    nonzeros = [(i, x , start_index-i) for i, x in enumerate(lst) if x != 0] 
    sorted_nonzeros = sorted(nonzeros, key=lambda x: abs(x[0] - start_index)) 
    return sorted_nonzeros[0][1] 

lst = [4,2,6,1,0,0,0,7,4,2,5,8,1,7] 

print(closest_nonzero(lst, 6)) # 1 
print(closest_nonzero(lst, 5)) # 7