[英]Deleting elements of a python list during iteration
我有我必须完成许多操作每个元素非常大名单。 本质上,列表的每个元素都以各种方式附加到其上,然后用于生成对象。 这些对象然后用于生成另一个列表。
不幸的是,以幼稚的方式执行此操作会占用所有可用内存。
因此,我想做以下事情:
for a in b:
# Do many things with a
c.append(C(modified_a))
b[b.index(a)] = None # < Herein lies the rub
这似乎违反了在迭代过程中不应修改列表的想法。 有没有更好的方法来进行这种手动垃圾收集?
这应该不成问题,因为您只是将新值分配给列表元素,而不是真正删除它们。
但是,可能不应该使用枚举来搜索索引方法,而不必使用index方法。
另请参见此处: http : //unspecified.wordpress.com/2009/02/12/thou-shalt-not-modify-a-list-during-iteration/ “首先,请允许我在本文中明确指出说“修改”,我的意思是从列表中插入或删除项目。仅更新或变异列表项目就可以了。”
您的代码有几个问题。
首先,为列表元素分配None
不会将其删除:
>>> l=[1,2,3,4,5,6,6,7,8,9]
>>> len(l)
10
>>> l[l.index(5)]=None
>>> l
[1, 2, 3, 4, None, 6, 6, 7, 8, 9]
>>> len(l)
10
其次,使用索引查找要更改的元素根本不是有效的方法。
您可以使用枚举,但是您仍然需要遍历以删除None
值。
for i,a in enumerate(b):
# Do many things with a
b[i]=C(modified_a)
b[i]=None
c=[e for e in b if e is not None]
您可以使用列表推导将新的“ a”值复制到c列表中,然后删除b:
c=[do_many_things(a) for a in b]
del b # will still occupy memory if not deleted...
或者,如果您想在适当位置修改b,则可以使用slice分配 :
b[:]=[do_many_things(a) for a in b]
切片分配以这种方式工作:
#shorted a list
>>> b=[1,2,3,4,5,6,7,8,9]
>>> b[2:7]=[None]
>>> b
[1, 2, None, 8, 9]
#expand a list
>>> c=[1,2,3]
>>> c[1:1]=[22,33,44]
>>> c
[1, 22, 33, 44, 2, 3]
# modify in place
>>> c=[1,2,3,4,5,6,7]
>>> c[0:7]=[11,12,13,14,15,16,17]
>>> c
[11, 12, 13, 14, 15, 16, 17]
您可以像这样在列表理解中使用它:
>>> c=list(range(int(1e6)))
>>> c[:]=[e for e in c if e<10]
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
其中一项评论指出,切片分配未完全修改到位。 生成临时列表。 那是真实的。 但是,让我们在这里查看总时间:
import time
import random
fmt='\t{:25}{:.5f} seconds'
count=int(1e5)
a=[random.random() for i in range(count)]
b=[e for e in a]
t1=time.time()
for e in b:
if e<0.5: b[b.index(e)]=None
c=[e for e in b if e is not None]
print(fmt.format('index, None',time.time()-t1))
b=[e for e in a]
t1=time.time()
for e in b[:]:
if e<0.5: del b[b.index(e)]
print(fmt.format('index, del',time.time()-t1))
b=[e for e in a]
t1=time.time()
for i,e in enumerate(b[:]):
if e<0.5: b[i]=None
c=[e for e in b if e is not None]
print(fmt.format('enumerate, copy',time.time()-t1))
t1=time.time()
c=[e for e in a if e<.5]
del a
print(fmt.format('c=',time.time()-t1))
b=[e for e in a]
t1=time.time()
b[:]=[e for e in b if e<0.5]
print(fmt.format('a[:]=',time.time()-t1))
在我的计算机上,打印以下内容:
index, None 87.30604 seconds
index, del 28.02836 seconds
enumerate, copy 0.02923 seconds
c= 0.00862 seconds
a[:]= 0.00824 seconds
或者,如果这样做没有帮助,请使用numpy以获得更优化的数组选项。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.