Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python2.7-list.remove(项)在循环中产生意外行为_Python_Python 2.7 - Fatal编程技术网

Python2.7-list.remove(项)在循环中产生意外行为

Python2.7-list.remove(项)在循环中产生意外行为,python,python-2.7,Python,Python 2.7,我想删除列表中的所有偶数。但有些事情让我困惑。。。 这是代码 lst = [4,4,5,5] for i in lst: if i % 2 == 0: print i lst.remove(i) print lst 它打印[4,5,5]为什么不打印[5,5]?应该是这样的 for i in lst[:]: if i % 2 == 0: print i lst.remove(i) print lst 问题:

我想删除列表中的所有偶数。但有些事情让我困惑。。。 这是代码

lst = [4,4,5,5]

for i in lst:
    if i % 2 == 0:
        print i
        lst.remove(i)

print lst

它打印[4,5,5]为什么不打印[5,5]?

应该是这样的

for i in lst[:]:
    if i % 2 == 0:
        print i
        lst.remove(i)

print lst
问题:


您正在修改列表,同时对其进行迭代。因此,迭代在完成之前就停止了

解决方案:

您可以遍历列表的副本

您可以使用
列表理解

lst=[i for i in lst if i%2 != 0]

通过使用
list.remove
,您可以在迭代过程中修改列表。这会中断迭代,给您带来意想不到的结果

一种解决方案是使用
过滤器
或列表理解创建新列表:

>>> filter(lambda i: i % 2 != 0, lst)
[5, 5]
>>> [i for i in lst if i % 2 != 0]
[5, 5]

如果需要,可以将任一表达式指定给
lst
,但不能避免使用这些方法创建新的列表对象。

作为一般原则,在迭代集合时不应修改它。这会导致跳过某些元素,并在某些情况下导致索引错误

与其从列表中删除元素,不如创建另一个同名的引用。它的时间复杂度也较小

lst = filter(lambda i: i % 2 !=0, lst)

其他答案已经提到,您在迭代列表时正在修改列表,并提供了更好的方法。我个人更喜欢列表理解法:

odd_numbers = [item for item in numbers if item % 2 != 0]
对于您指定的非常小的列表的情况,我肯定会同意

然而,这确实会创建一个新的列表,如果您有一个非常大的列表,这可能是一个问题。在整数的情况下,大可能至少意味着数百万,但准确地说,它需要多大才能开始给您带来内存使用问题。在这种情况下,有几种方法可以做到这一点

一种方法与问题中代码的意图类似。您在列表上进行迭代,同时删除偶数。但是,为了避免修改正在迭代的列表可能导致的问题,您可以向后迭代它。有很多方法可以向前迭代,但这更简单

下面是使用
while
循环的一种方法:

# A one hundred million item list that we don't want to copy
# even just the odd numbers from to put into a new list.
numbers = range(100000000)  # list(range(100000000)) in Python 3

index = len(numbers) - 1  # Start on the index of the last item
while index >= 0:
    if numbers[index] % 2 == 0:
        numbers.pop(index)
    index -= 1
# A one hundred million item list that we don't want to copy
# even just the odd numbers from to put into a new list.
numbers = range(100000000)  # list(range(100000000)) in Python 3

for index in xrange(len(numbers) - 1, -1, -1):  # range(...) in Python 3
    if numbers[index] % 2 == 0:
        numbers.pop(index)
下面是另一种使用
for
循环的方法:

# A one hundred million item list that we don't want to copy
# even just the odd numbers from to put into a new list.
numbers = range(100000000)  # list(range(100000000)) in Python 3

index = len(numbers) - 1  # Start on the index of the last item
while index >= 0:
    if numbers[index] % 2 == 0:
        numbers.pop(index)
    index -= 1
# A one hundred million item list that we don't want to copy
# even just the odd numbers from to put into a new list.
numbers = range(100000000)  # list(range(100000000)) in Python 3

for index in xrange(len(numbers) - 1, -1, -1):  # range(...) in Python 3
    if numbers[index] % 2 == 0:
        numbers.pop(index)
请注意,在
while
循环和
for
循环版本中,我使用了
numbers.pop(index)
,而不是
numbers.remove(numbers[index])
。首先,
.pop()
效率更高,因为它提供了索引,而
.remove()
必须在列表中搜索第一次出现的值。第二,注意我说的“值的第一次出现”。这意味着,除非每个项目都是唯一的,否则使用
.remove()
将删除与循环当前所在项目不同的项目,从而将当前项目保留在列表中

我还想提一个解决方案,用于需要保留原始列表但不想使用太多内存来存储奇数副本的情况。如果您只想在奇数上迭代一次(或者您非常讨厌使用内存,以至于在需要时宁愿重新计算),您可以使用生成器。这样做可以让您在不需要任何额外内存的情况下迭代列表中的奇数,除了生成器机制使用的不合理数量之外

生成器表达式的定义与列表理解完全相同,只是它被括在括号中而不是方括号中:

odd_numbers = (item for item in numbers if item % 2 != 0)
请记住,生成器表达式正在对原始列表进行迭代,因此在迭代过程中更改原始列表会给您带来与在
for
循环中对列表进行迭代时修改列表相同的问题。事实上,生成器表达式本身使用
for
循环

顺便说一句,生成器表达式不应该只归入非常大的列表;每当我不需要一次性计算整个列表时,我都会使用它们

概要/TLDR: “最好”的方法取决于你在做什么,但这应该涵盖很多情况

假设列表为“小”或“大”:

如果列表很小,请使用列表理解(如果可以,甚至可以使用生成器表达式)。如果它很大,请继续阅读

如果不需要原始列表,请使用
while
循环或
for
循环方法完全删除偶数(尽管使用
.pop()
,而不是
.remove()
)。如果您确实需要原始列表,请继续阅读

如果只对奇数迭代一次,请使用生成器表达式。如果要对它们进行多次迭代,但希望重复计算以节省内存,请使用生成器表达式


如果您对奇数进行了太多次迭代,以至于每次都无法重新计算它们,或者您需要随机访问,那么请使用列表理解来创建一个仅包含奇数的新列表。它将使用大量内存,但它们是中断。

您在迭代列表时正在修改列表。这扰乱了迭代。@Sam很高兴help@Sam,不客气。别忘了给好答案投票(不仅仅是我的),并接受对你最有帮助的答案(即使不是我的:P)。是的,是的,这很正常。。如果有帮助,请将其标记为正确答案