0

我刚刚在这里阅读了一篇关于如何从两个列表中过滤值的帖子。python:如何根据 1 个列表中的内容从 2 个列表中删除值

我尝试使用forand自己编写一些代码zip,但结果是错误的,谁能帮助我理解这一点?

xVar = [1, 2, 3, 4, 5, 6, 7]
yVar = [11, 22, 33, 44, 55, 66, 77]

z = zip(xVar, yVar)
zFiltered = [(x, y) for x, y in z if y < 50]
print zFiltered # Correct, prints [(1, 11), (2, 22), (3, 33), (4, 44)]

for (x, y) in z:
    if y > 50:
        z.remove((x, y))

print z # Wrong, prints [(1, 11), (2, 22), (3, 33), (4, 44), (6, 66)]

为什么会这样?我尝试使用pdb后发现 ,z.remove((5, 55))(x, y)值是(7, 77),(6, 66)被跳过,我假设for是通过索引分配(x, y),删除(5, 55)会违反原始索引,如果是这样,我怎么能在这里用for语句做同样的事情?这里还有其他陷阱吗?

4

2 回答 2

3

试试这个列表推导,它将根据条件选择压缩列表中的元素(基本上与从列表中删除不满足此条件的元素相反,但它会产生相同的结果)。

z = [(x, y) for (x, y) in z if y <= 50]

如果要在迭代列表时删除列表中的元素,则必须向后迭代,因为每次删除列表中的项目时,列表中具有较高索引的所有元素都会向下移动到较低索引。

您可以像这样进行这样的迭代:

for i in xrange(len(z) -1, -1, -1):
    if z[i][1] > 50:
        z.remove(z[i])
于 2013-09-26T06:03:32.827 回答
2

问题是,当您在迭代列表时从列表中删除项目时,其内部结构会出现问题,并且项目会被跳过。解决此问题的简单方法是通过添加来制作列表的副本[:]

for (x, y) in z[:]:
    ...

现在您可以对原始列表进行更改,因为它没有被迭代。

于 2013-09-26T06:24:01.077 回答