python删除列表中值的所有条目

时间:2015-08-28 05:02:43

标签: python

为什么循环不起作用?我的目标是从列表中删除每个1

>>> s=[1,4,1,4,1,4,1,1,0,1]
>>> for i in s:
...   if i ==1: s.remove(i)
... 
>>> s
[4, 4, 4, 0, 1]

4 个答案:

答案 0 :(得分:6)

迭代时不要更改列表。结果是不可预测的,正如您在这里看到的那样。一个简单的替代方案是构建一个新列表:

s = [i for i in s if i != 1]

如果由于某种原因你绝对需要编辑列表而不是构建一个新列表,我的袖手旁观的最佳答案是遍历它找到必须删除的索引,然后反向遍历索引列表逐个删除它们:

indices_to_remove = [i for (i, val) in enumerate(s) if val == 1]
for i in reversed(indices_to_remove):
    del s[i]

因为它首先从列表末尾删除元素,所以计算出的原始索引仍然有效。但除非特殊情况适用,否则我通常更喜欢计算新列表。

答案 1 :(得分:5)

考虑以下代码:

  #!/usr/bin/env python

  s=[1, 4, 1, 4, 1, 4, 1, 1, 0, 1]
  list_size=len(s)
  i=0

  while i!=list_size:
      if s[i]==1:
          del s[i]
          list_size=len(s)
      else:
          i=i + 1

  print s

结果:

[4, 4, 4, 0]

简而言之,您的代码会产生一些不良结果,因为每次关闭1数字时,列表的“大小”和“索引位置”都会更改,并且您的代码已明确证明{{1} for each loop中的{}无法处理动态大小的列表。

答案 2 :(得分:3)

这不起作用,因为您在迭代时修改列表,并且当前指针移过您检查的1之一。我们可以说明这一点:

>>> for i in s:
...   print(s)
...   if i == 1:
...      s.remove(i)
... 
[1_, 4, 1, 4, 1, 4, 1, 1, 0, 1]
[4, 1_, 4, 1, 4, 1, 1, 0, 1]
[4, 4, 1_, 4, 1, 1, 0, 1]
[4, 4, 4, 1_, 1, 0, 1]
[4, 4, 4, 1, 0_, 1]
[4, 4, 4, 1, 0, 1_]

我将_添加到要比较的元素中。请注意,总共只有6次传递,并且其中一个1实际上已被跳过了。这最终成为被移除的元素,因为list.remove删除了指定元素的第一次出现,并且它本身就是一个O(n)操作,一旦你的列表获得非常昂贵变大 - 这是O(n)即使项目在开头,因为它必须从项目一元素前面的所有内容复制每一个项目,因为python list更像是C样式的数组而不是Java链接列表(如果要使用链接列表,请使用collections.deque)。 O(n)即将结束,因为它必须遍历整个列表以进行自己的比较。如果您使用remove,生成的代码可能会导致运行时最严重的O(n log n)。

请参阅Python's data structure time complexity

彼得的回答已经涵盖了新列表的生成,我只回答了原始代码无法正常工作的原因和方式。

答案 3 :(得分:3)

迭代时不应更改列表的内容

但是你可以迭代列表内容的副本并在你的情况下改变它

<强>代码:

s=[1,4,1,4,1,4,1,1,0,1]
for i in s[:]:
    if i ==1: s.remove(i)
print s

<强>输出:

[4, 4, 4, 0]

正如@metatoaster所说,你可以使用filter

<强>代码:

s=[1,4,1,4,1,4,1,1,0,1]
s=list(filter(lambda x:x !=1,s))
print s
[4, 4, 4, 0]

您可以使用过滤器删除多个示例

<强>代码:

s=[1,4,1,4,1,4,1,1,0,1,2,3,5,6,7,8,9,10,20]
remove_element=[1,2,3,5,6,7,8,9]
s=list(filter(lambda x:x not in remove_element,s))
print s
[4, 4, 4, 0, 10, 20]