我参加了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。请帮忙,我不知道如何解决这个问题。
答案 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)