(无意地)在迭代列表时跳过项目

3

I have a list and I want to remove from it the items that don't appear in another list. I've tried the following:

for w in common:
        for i in range(1,n):
            if not w in words[i]:
                common.remove(w)
However, this fails to remove some of the items. Adding print statements
for w in common:
        for i in range(1,n):
                        print w
            if not w in words[i]:
                print w
                common.remove(w)
results in some w never being printed. Any ideas as to what's happening? I assume the answer's simple and I just don't have adequate Python knowledge, but I'm completely out of ideas.


为了提高效率,你应该将 common 定义为一个 set,因为在集合中检查成员比在列表中更快。 - Katriel
5个回答

8

我认为您可以通过以下方式简化您的陈述:

filtered = filter(lambda x: x in words, common)

那就检查每个共同元素是否存在于单词中,并基于此进行删除。根据您的期望结果,您可能需要尝试x not in words,但我认为这应该接近您想要的结果。 我想再添加一种方法,也可以接近,但我需要看一下您初始列表的示例以全面测试它。
filtered = [x for x in common if x in words]

-- 编辑 -- 我在列表推导式中的语法是反过来的,但在看到评论后发现了这个问题。谢谢!


2
不错,但我更喜欢 filtered = [x for x in common if x in words] 或者 filtered = filter(words.__contains__, common) 或者在这种情况下使用 operator.contains 而不是 lambda。可能会选择第一个。 - Muhammad Alkarouri
它变得越来越Pythonic了,越来越Pythonic了 ;) - Nicolas78
谢谢穆罕默德。我第二个想到了列表推导式。虽然感谢您的反馈。 :) - g.d.d.c

3

您不能从正在迭代的列表中删除项目。请尝试迭代列表的副本。

for w in common[:]:
    for i in range(1,n):
        if not w in words[i]:
            common.remove(w)

3

来自Python文档

在循环中修改正在迭代的序列是不安全的(这只适用于可变序列类型,如列表)。如果您需要修改正在迭代的列表(例如复制选定项目),则必须迭代副本。


2
你在迭代列表时修改了它。 您可以将代码的第一行更改为通过副本迭代列表(使用common[:])。

2
如果您删除(比如说)第5项,则旧的第6项现在将成为第5项。因此,如果您想移至第6项,则会跳过它。
是否可以倒序迭代该列表?这样,索引更改会发生在您已经处理过的部分。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接