在for循环中从Python列表中移除元素

0 投票
3 回答
844 浏览
提问于 2025-04-16 02:18

这是我的代码:

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]:”这样的写法。我还没有尝试过这种方法。

撰写回答