2

尝试删除列表中的项目,没有成功。

>>> r = [1,2,3,4,5]
>>> for i in r:
    if i<3:
        del i


>>> print r
[1, 2, 3, 4, 5]

我什至尝试过滤它,

>>> def f(i):
    True if i>2 else False


>>> print list(filter(f,r))
[]

我不明白为什么第一个不起作用。当我使用filter(function,iterable).

编辑:

看到下面保罗的评论,现在我不明白为什么会这样。

>>> for i in r:
    if i<3:
        r.remove(i)


>>> print r
[3, 4, 5]

迭代器问题不应该仍然存在吗,代码不应该最终只删除第一个元素(r[0]

4

2 回答 2

10

改用列表推导:

[i for i in r if i >= 3]

并保留而不是删除。

您的过滤器从未返回测试;所以你总是返回None,这在布尔上下文中是错误的。以下工作正常:

def f(i):
    return i > 2

您的初始尝试失败,因为del iunbinds i,但列表不受影响。i仅清除本地名称。

如果要从列表中删除项目,则需要删除索引:

del r[0]

从列表中删除第一个元素。

即使您确实设法删除了索引,循环也会带来一些惊喜:

>>> for i, element in enumerate(r):
...     if element < 3:
...         del r[i]
... 
>>> r
[2, 3, 4, 5]

此版本失败,因为for循环使用的列表迭代器不知道您从列表中删除了元素;删除索引 0 处的值会向上移动列表的其余部分,但循环迭代器会查看第 1 项,不管:

  • 第一次迭代, r = [1, 2, 3, 4, 5], 迭代器索引 0 ->element = 1
  • 第二次迭代, r = [2, 3, 4, 5], 迭代器索引 1 ->element = 3
于 2013-09-23T19:59:43.380 回答
4

我不明白为什么第一个不起作用。

它不起作用,因为该语句del i取消定义变量i- 也就是说,它从包含它的范围(全局或本地)中删除它。

当我使用 filter(function,iterable) 时,我根本不理解结果

您的函数f不包含 return 语句。因此,它总是返回None,它的布尔等效值为False。因此,filter排除所有值。


您可能应该做的是使用理解进行过滤,并替换列表,如下所示:

r = [i for i in r if i >= 3]

或者,如果您确实想删除原始列表的一部分并对其进行修改,请del在列表的一部分上使用:

del r[:3]

看到下面 Paulo 的评论,现在我不明白为什么 [using remove] 有效。

因为在列表中remove(r)搜索值r,并删除它的第一个实例。因此,列表的重复修改不会影响内部发生的迭代remove。但是,请注意,如果删除项目导致在列表迭代中跳过项目,它仍然容易受到相同错误的影响。

于 2013-09-23T20:04:33.567 回答