2016-08-20 84 views
-1

任何人都可以理解爲什麼下面的代碼失敗?繞過條件

def main(A): 
    A.sort() 
    B = A[:] 
    ll = len(B) 
    while ll > 1: 
     for i in range(ll): 
      for n in range(i + 1, ll): 
       if (B[i] + B[n]) % 2 == 0: 
        B.remove(B[n]) 
        B.remove(B[i]) 
        main(B) 
    return B 
if __name__ == '__main__': 
    result = main([4, 5, 3, 7, 2]) 
    print(result) 

它運行正常,直到我的列表只有一個值,達到「返回B」語句,然後它又跳回到循環中。我錯過了什麼?

+1

你是遞歸,調用'主(B)'和忽略返回值。由於您每次都在製作「A」的*副本,忽略返回值*重要*。 –

+0

我給出幾個理由說明爲什麼你的代碼在我的答案中可能「失敗」。對於更詳細的答案,包括任何*機會*在工作解決方案,請包括你的問題一個適當的[麥克];錯誤和*預期結果*的完整追溯,即函數*應該做什麼*。 –

回答

1

您正在使用遞歸,在循環中再次調用main(B)。當遞歸調用返回時,您稱之爲的循環繼續在上。

而且,您忽略了遞歸調用的返回值。由於您在main()的每個調用中使用列表的副本,因此忽略返回值意味着您放棄了遞歸調用所做的所有工作。

最後但並非最不重要的一點是,您正在從B刪除元素;您將遇到循環索引錯誤,因爲in範圍爲ll,這是刪除元素後不再有效的長度。由於您無法更新正在循環的range()對象;你不得不使用while循環,即測試長度每次迭代:

i = 0 
while i < len(B): 
    n = i + 1 
    while n < len(B): 
     if (B[i] + B[n]) % 2 == 0: 
      del B[n], B[i] 
      break 
     else: 
      n += 1 
    else: 
     i += 1 

上述循環將從該總結爲偶數的列表中刪除任何兩個數字。請注意,當您同時刪除ni值時,可以使用索引,而不是使用list.remove()搜索該號碼。

內部while循環使用else套件;這隻有當你不要跳出循環時纔會執行,只有當我們不只是刪除索引i處的值時纔會發生這種情況。所以當你不要找到B[i]的配對時,i會遞增以轉到下一個候選人。如果你找到配對, the value atis deleted, so now B [i]`已經引用下一個值。

我不知道爲什麼你需要在這個循環後遞歸;遞歸調用不會找到更多這樣的配對,因爲您已經測試了每個組合

演示,通過使用sorted()在複印補充說:

>>> def main(A): 
...  B = sorted(A) 
...  i = 0 
...  while i < len(B): 
...   n = i + 1 
...   while n < len(B): 
...    if (B[i] + B[n]) % 2 == 0: 
...     del B[n], B[i] 
...     break 
...    else: 
...     n += 1 
...   else: 
...    i += 1 
...  return B 
... 
>>> main([4, 5, 3, 7, 2]) 
[7] 
+0

非常好的見解。謝謝Martijn Pieters。我沒有索引錯誤,直到代碼「忽略」返回值並再次跳入循環。再次感謝您的幫助。 –

+0

@VagelisProkopiou:這只是因爲你沒有達到外部循環中的索引錯誤條件**但是**。它也會到達那裏。 –

+0

Thanx。你是對的。編碼忍者的確如此! –