在for循环中从Python列表中移除元素
这是我的代码:
toBe =[]
#Check if there is any get request
if request.GET.items() != []:
for x in DB:
try:
#This is removing the PMT that is spcific to the name
if request.GET['pmtName'] != "None":
if not request.GET['pmtName'] in x['tags']:
print x['title'], x['tags']
toBe.append(x)
continue
#This is removing the peak stuff
if int(request.GET['peakMin']):
if int(request.GET['peakMin']) < int(x['charge_peak']):
toBe.append(x)
continue
if int(request.GET['peakMax']):
if int(request.GET['peakMax']) > int(x['charge_peak']):
toBe.append(x)
continue
if int(request.GET['widthMin']):
if int(request.GET['widthMin']) < int(x['charge_width']):
toBe.append(x)
continue
if int(request.GET['widthMax']):
if int(request.GET['widthMax']) > int(x['charge_width']):
toBe.append(x)
continue
except:
pass
#TODO: Stupid hack, this needs to be fixed
for x in toBe:
DB.remove(x)
del toBe
基本上,我想删除一个项目,然后跳到下一个。但是这样做的问题是,当我删除后,列表的顺序会被搞乱,还会跳过一些项目。有没有人知道有什么解决办法?或者有没有其他的方法可以做到这一点?
谢谢
3 个回答
0
你在对每个 x
的值都重复使用同样的 request.GET
的处理方式。其实你可以先建立一个可以重复使用的过滤函数列表。
比如可以这样做:
if request.GET:
filters = []
if 'pmtName' in request.GET:
n = request.GET['pmtName']
filters.append(lambda x: n not in x['tags'])
if 'peakMin' in request.GET and request.GET['peakMin'].isdigit():
n = int(request.GET['peakMin'])
filters.append(lambda x: n < int(x['charge_peak']))
if 'peakMax' in request.GET and request.GET['peakMax'].isdigit():
n = int(request.GET['peakMax'])
filters.append(lambda x: n > int(x['charge_peak']))
if 'widthMin' in request.GET and request.GET['widthMin'].isdigit():
n = int(request.GET['widthMin'])
filters.append(lambda x: n < int(x['charge_width']))
if 'widthMax' in request.GET and request.GET['widthMax'].isdigit():
n = int(request.GET['widthMax'])
filters.append(lambda x: n > int(x['charge_width']))
然后你可以用这个函数列表来选择要从数据库中移除的成员:
remove_these = [ x for x in DB if any(f(x) for f in filters)]
for item in remove_these:
DB.remove(item)
或者创建一个生成器,它会返回那些所有过滤条件都不符合的数据库值:
filtered_DB = ( x for x in DB if all(not f(x) for f in filters))
1
for x in DB[:]:
这段代码会复制列表 DB
,这样你就可以在修改原始列表的同时遍历它。不过要注意,这样会占用很多内存,而且速度比较慢。
一个更好的方法是为列表再加一层,只提取出你需要的一部分值,然后在需要的时候再遍历这个新层。你可以使用生成器来实现:
def db_view( DB ):
for x in DB:
#This is removing the PMT that is spcific to the name
if request.GET.get( 'pmtName', None ) not in x['tags']:
print x['title'], x['tags']
continue
#This is removing the peak stuff
if int(request.GET['peakMin']):
if int(request.GET['peakMin']) < int(x['charge_peak']):
continue
if int(request.GET['peakMax']):
if int(request.GET['peakMax']) > int(x['charge_peak']):
continue
if int(request.GET['widthMin']):
if int(request.GET['widthMin']) < int(x['charge_width']):
continue
if int(request.GET['widthMax']):
if int(request.GET['widthMax']) > int(x['charge_width']):
continue
yield x
你可以像这样使用它
for x in db_view( DB ):
# Do stuff
0
我通常看到的解决这类问题的方法是从后往前遍历列表。下面是我在一个程序中是怎么做的:
for i in range(len(my_list)-1,-1,-1):
# do something
这样做即使我往列表里添加了新项目也能正常工作。在这个链接上,他们说你可以用“for i in list[::-1]:”这样的写法。我还没有尝试过这种方法。