我刚刚在这里阅读了一篇关于如何从两个列表中过滤值的帖子。python: How to remove values from 2 lists based on what's in 1 list
我尝试使用for
和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
语句执行相同的操作?还有其他任何陷阱吗?
答案 0 :(得分: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])
答案 1 :(得分:2)
问题是当你在迭代它时从列表中删除一个项目时,它的内部结构就会失败,并且会跳过项目。解决此问题的简单方法是通过添加[:]
来制作列表的副本。
for (x, y) in z[:]:
...
现在您可以对原始列表进行更改,因为它没有被迭代。