我正在尝试从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)
但它不会删除"fren"
项。有什么想法吗?
答案 0 :(得分:88)
迭代时,您无法从列表中删除项目。基于旧列表构建新列表要容易得多:
y = [s for s in x if len(s) == 2]
答案 1 :(得分:39)
x[:] = [value for value in x if len(value)==2]
但是,对于需要删除少量元素的大型列表,这是耗费内存的,但它以O(n)运行。
glglgl的答案受到O(n²)复杂性的影响,因为list.remove
是O(n)。
根据数据的结构,您可能更愿意注意要删除元素的索引,并使用del
键工作来删除索引:
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]
现在del x[i]
也是O(n),因为您需要复制索引i
之后的所有元素(列表是向量),因此您需要针对您的数据进行测试。这仍然比使用remove
更快,因为您不支付删除搜索步骤的成本,并且复制步骤成本在两种情况下都相同。
[编辑]非常好的就地,O(n)版本,内存要求有限,由@Sven Marnach提供。它使用python 2.7中引入的itertools.compress
:
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
答案 2 :(得分:5)
x = [i for i in x if len(i)==2]
答案 3 :(得分:2)
这源于这样一个事实:在删除时,迭代会跳过一个元素,因为semms只能处理索引。
解决方法可能是:
x = ["ok", "jj", "uy", "poooo", "fren"]
for item in x[:]: # make a copy of x
if len(item) != 2:
print "length of %s is: %s" %(item, len(item))
x.remove(item)
答案 4 :(得分:2)
已经提到的列表理解方法可能是你最好的选择。但如果您绝对想要就地执行此操作(例如,如果x
非常大),可以采用以下方法:
x = ["ok", "jj", "uy", "poooo", "fren"]
index=0
while index < len(x):
if len(x[index]) != 2:
print "length of %s is: %s" %(x[index], len(x[index]))
del x[index]
continue
index+=1