Python成员限制测试?

2024-09-30 04:36:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个问题,我用一个方法来测试在一个地理位置列表中的成员资格,并从一个没有通过这个检查的预算列表中删除条目。有趣的是,这个方法需要运行3次才能捕获100%的失败条目。你知道吗

budg元素示例:

budg = ['KELOG_PSOD_32773                                  20131125 000327   73144652.3376898.6 9769.50', 'KELOG_PSOD_32774                                  20131125 000327   74140034.3406629.9 4473.90']

地理元素示例:

geolist = ['KELOG_GEO_32773','KELOG_GEO_32775']

def remove_entry(budg, geolist):
    for e in budg:
        record = 'KELOG_GEO_' + e[11:e.index(' ')]
        if record not in geolist:
            print e
            removed.append(budg.pop(budg.index(e)))

我运行这个列表,每个大约有2500个条目。截至今天,有44个未通过的条目存在于预算清单中。运行此方法一次后,budg列表中始终有7个误报。然后他们中的4个被抓到再次运行它。最后剩下的3个在第三次运行中被发现。我知道我可以在脚本中运行这个方法3次,然后一天调用一次,但这已经开始困扰我了。你知道吗

我尝试对列表进行反向排序,有趣的是,在第一次尝试时,我从44个失败条目中提取了37个条目,但其中一些条目将在第二次运行,如果不对列表进行反向排序,则第三次运行的结果将是。你知道吗

您是否知道我可能违反此代码对成员资格测试的任何限制?你们中有人见过这样的行为吗?你知道吗


Tags: 方法in元素示例列表index条目成员
3条回答

问题是你正在改变你正在迭代的列表。避免这种情况的方法不止一种。一个简单易懂且快速的方法是创建一个新的列表,去掉你想删除的项目,然后用它替换原来的列表。我的意思是:

budg = ['KELOG_PSOD_32773                                  20131125 000327   73144652.3376898.6 9769.50',
        'KELOG_PSOD_32774                                  20131125 000327   74140034.3406629.9 4473.90']

geoset = {'KELOG_GEO_32773', 'KELOG_GEO_32775'}  # note this is now a set

def remove_entry(budg, geoset):
    cleaned = []
    for e in budg:
        record = 'KELOG_GEO_' + e[11:e.index(' ')]
        if record in geoset:  # keep it
            cleaned.append(e)
    budg[:] = cleaned

remove_entry(budg, geolist)
print 'budg:', budg

这种方法的另一个优点是,它可以简化为一行代码:

budg = [e for e in budg if 'KELOG_GEO_' + e[11:e.index(' ')] in geoset]

正如在修订后的代码开头的注释中所指出的,我将geolist改为geoset,因为在set中测试成员身份通常比在列表中检查成员身份要快得多(如果列表很大)。你知道吗

迭代时不应从列表中删除元素。原因是,这会修改要删除的元素的索引,进而更改循环将继续其迭代的位置。你知道吗

您应该先确定要删除哪些元素,然后再删除它们。你知道吗

您正在从budg中移除元素,同时在其上循环。执行此操作时,for循环迭代器不会更新其索引:

>>> lst = [1, 2, 3]
>>> for i in lst:
...     print i
...     lst.remove(i)
... 
1
3

这里跳过了2,因为迭代器首先处理lst[0],然后移到lst[1],此时它来自一个包含[2, 3]的列表,而不是[1, 2, 3]。你知道吗

改用while循环:

i = 0
while i < len(budg):
    e = budg[i]
    record = 'KELOG_GEO_' + e.split(None, 1)[0][11:]
    if record not in geolist:
        removed.append(budg.pop(i))
    else:
        i += 1

现在您可以直接控制正在处理的索引,并且只在而不是删除元素时增加i。你知道吗

相关问题 更多 >

    热门问题