python函数的奇怪行为

时间:2016-10-02 02:28:08

标签: python function

我参加了Python的edx在线课程,我必须做这个小程序,我认为该功能是正确的,但是当从List中删除一个元素突然下一个元素是不考虑进入测试。

    def f(i):
       return i + 2
    def g(i):
       return i > 5


    def applyF_filterG(L, f, g):
        """
        Assumes L is a list of integers
        Assume functions f and g are defined for you. 
        f takes in an integer, applies a function, returns another integer 
        g takes in an integer, applies a Boolean function, 
        returns either True or False
        Mutates L such that, for each element i originally in L, L contains  
            i if g(f(i)) returns True, and no other elements
        Returns the largest element in the mutated L or -1 if the list is empty
        """
        # Your code here
        i = 0
        if len(L) == 0:
            return -1
        while i < len(L):
            if not g(f(L[i])):
                del L[i]
            i += 1
        return max(L)

如果我尝试这个例子L = [0,-10,5,6,-4,-2],L的值应该是L = [5,6],但结果是这个[-10, 5,6,-2]当删除0时跳过元素-10,同样发生-4和-2。请帮忙,我不知道如何解决这个问题。

4 个答案:

答案 0 :(得分:3)

问题:

在迭代列表时,您将从列表中删除元素。因此,i不再引用列表中的正确元素。

为了说明这个问题,这里有一个运行代码的示例 对于这个例子,我们假设if语句删除一个元素,如果它的值是偶数。
我还假设i已经初始化。

  

L = [1,2,6,3,4]

     

迭代1

     

i == 0,L [i] == 1,我们不删除该元素    L == [1,2,6,3,4]

     

迭代2

     

i == 1,L [i] == 2,元素被删除    L == [1,6,3,4]

     

迭代3

     

i == 2,L [i] == 3,我们不删除该元素    L == [1,6,3,4]
  #你注意到我们刚刚跳过检查6,因为它的索引被移动了吗?!

     

迭代4

     

i == 3,L [i] == 4,元素被删除    L == [1,6,3]

     

我们结束了!

有几种方法可以做到这一点。虽然@Meerness已经提供了一种方法,但这是另一种方法,只是为了完整性。

i = len(L) - 1
if i == -1:
    return -1

while i >= 0:
    if not g(f(L[i])):
        del L[i]
    i -= 1

这是如何运作的:

通过这种方式,您可以从最顶层的索引算起来。这样,删除元素不会影响您仍未检查的元素的索引 我对这种做法的解释是@JohnColeman对评论的略微改写版本。
但是,在我看到他的评论之前,我已经写过这个解决方案,所以我没有借用他的想法 - 我只是借用了他的解释。 :)

以下是我们倒计时而非计算时会发生什么的示例:

  

L = [1,2,6,3,4]

     

迭代1

     

i == 4,L [i] == 4,元素被删除    L == [1,2,6,3]

     

迭代2

     

i == 3,L [i] == 3,我们不删除该元素    L == [1,2,6,3]

     

迭代3

     

i == 2,L [i] == 6,元素被删除    L == [1,2,3]

     

迭代4

     

i == 1,L [i] == 2,元素被删除    L == [1,3]

     

迭代5

     

i == 0,L [i] == 1,我们不删除该元素    L == [1,3]

     

我们结束了!

PS:使用python3脚本自动生成的示例。 :)

答案 1 :(得分:3)

尽量不要遍历在Python中循环内部变异的列表。在此示例中,删除元素后索引顺序已更改。我在迭代它之前创建了一个L副本,它就可以解决问题。

def applyF_filterG(L, f, g):
    copied_L = L[:]
    for i in copied_L:
        if not g(f(i)):
            L.remove(i)
    if len(L)==0:
        return -1
    else:
        return  max(L)

答案 2 :(得分:2)

如果您正在迭代列表,那么这是一个坏主意,并会导致意外行为。一般来说,您最好创建一个新列表来处理。

在这种特定情况下,您的代码可以通过简单的修改来修复。如果您没有删除元素,则只迭代索引,以便不在列表中向前跳过。

while i < len(L):
    if not g(f(L[i])):
        del L[i]
    else:
        i += 1

答案 3 :(得分:0)

def applyF_filterG(L, f, g):
    """
    Assumes L is a list of integers
    Assume functions f and g are defined for you. 
    f takes in an integer, applies a function, returns another integer 
    g takes in an integer, applies a Boolean function, 
        returns either True or False
    Mutates L such that, for each element i originally in L, L contains  
        i if g(f(i)) returns True, and no other elements
    Returns the largest element in the mutated L or -1 if the list is empty
    """

    M =[]
    for i in range(len(L)):
       if g(f(L[i])):
            M.append(L[i])
    L = M[:]
    if len(L)==0:
        return -1
    else:
        return max(L)