2016-08-20 85 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。你是对的。编码忍者的确如此! –