循环导致列表越界

2 投票
3 回答
1612 浏览
提问于 2025-04-17 19:13

我正在尝试写一个函数,目的是在一个列表中查找并删除所有的奇数。但是我遇到了一个问题,我的循环超出了范围,我不知道该怎么解决。有没有人能帮帮我?谢谢!

def isEven(number):
    if(number % 2) == 0 and (number != 0):
        return True
    else:
        return False

def only_even(intList):
    for i in range(0, len(intList)):
        if(isEven(intList[i])) == False:
           del intList[i]
    return intList

print(only_even([5, 8, 17, 6, 0, 20, 3]))

3 个回答

1
def only_even(intList):
    intList[:] = filter(isEven, intList)
    return intList
def only_even(intList):
    return list(filter(isEven, intList))

或者,如果你不需要在原地修改这个列表:

2

列表超出范围的原因是因为你在缩小列表的同时,还在遍历原来的大小范围!

def only_even(intList):
    intList[:] = [i for i in intList if isEven(i)]
    return intList

我使用了切片赋值 [:] 来保持修改和返回列表的确切含义。如果你只是想返回列表,其实可以更简单。

def only_even(intList):
    return [i for i in intList if isEven(i)]

你还可以简化你的判断是否为偶数的函数,因为它已经能直接判断出是对还是错。

def isEven(number):
    return number % 2 == 0 and number != 0   # Why isn't 0 even?
2

当你使用 del 删除列表中的元素时,列表的长度会发生变化。但是 for 循环是根据原来的列表长度来进行遍历的,所以最终会出现超出列表范围的情况。也就是说,len(intList) 并不是每次 for 循环都重新计算的。

解决这个问题的方法是从旧列表创建一个新列表,然后返回这个新列表,像这样:

def only_even(intList):
    new_list = []
    for i in range(0, len(intList)):
        if isEven(intList[i]) == True:
            new_list.append(intList[i])
    return new_list

现在你的打印语句就可以正常工作了:

>>> print(only_even([5, 8, 17, 6, 0, 20, 3]))
[8, 6, 20]

撰写回答