如何从循环中的python列表中删除项?

alw*_*btc 58 python list

可能重复:
在Python中迭代时从列表中删除项目

我正在尝试从python中的列表中删除一个项目:

x = ["ok", "jj", "uy", "poooo", "fren"]
for item in x:
    if len(item) != 2:
        print "length of %s is: %s" %(item, len(item))
        x.remove(item)
Run Code Online (Sandbox Code Playgroud)

但它不会删除"fren"项目.有任何想法吗?

Sve*_*ach 92

迭代时,您无法从列表中删除项目.基于旧列表构建新列表要容易得多:

y = [s for s in x if len(s) == 2]
Run Code Online (Sandbox Code Playgroud)

  • @delnan:好吧,如果您以相反的顺序遍历列表,则可以*更多*,甚至可以获得有用的结果。但这可能不会比Sven建议的那样创建一个新列表更快(并且绝对会更加混乱)。 (2认同)

gur*_*lex 42

hymloth和sven的答案有效,但他们不修改列表(创建一个新的).如果需要修改对象,则需要分配给切片:

x[:] = [value for value in x if len(value)==2]
Run Code Online (Sandbox Code Playgroud)

但是,对于需要删除少量元素的大型列表,这是耗费内存的,但它在O(n)中运行.

glglgl的答案受到O(n²)复杂性的影响,因为list.remove是O(n).

根据数据的结构,您可能更喜欢注意要删除的元素的索引,并使用delkeywork来删除索引:

to_remove = [i for i, val in enumerate(x) if len(val)==2]
for index in reversed(to_remove): # start at the end to avoid recomputing offsets
    del x[index]
Run Code Online (Sandbox Code Playgroud)

现在del x[i]也是O(n)因为你需要在索引之后复制所有元素i(列表是向量),所以你需要针对你的数据进行测试.仍然这应该比使用更快,remove因为您不支付删除搜索步骤的成本,并且复制步骤成本在两种情况下都相同.

[编辑]非常好的就地,O(n)版本,内存要求有限,@Sven Marnach礼貌.它使用itertools.compresspython 2.7中引入的:

from itertools import compress

selectors = (len(s) == 2 for s in x)
for i, s in enumerate(compress(x, selectors)): # enumerate elements of length 2
    x[i] = s # move found element to beginning of the list, without resizing
del x[i+1:]  # trim the end of the list
Run Code Online (Sandbox Code Playgroud)

  • 这是一个就地O(n)版本,只需要额外的O(1)内存:http://ideone.com/F10fB.它不比你的O(n ^ 2)版本复杂.(+1详细解答,顺便说一句) (3认同)

hym*_*oth 5

x = [i for i in x if len(i)==2]
Run Code Online (Sandbox Code Playgroud)