奇怪的行为从Python中的循环中的列表中删除元素
我知道,如果您当前正在遍历该列表,则无法从列表中删除元素。我想要做的是从列表中复制我不希望移除到另一个列表中的元素,然后用新列表替换原始列表。这里是我的相关代码:奇怪的行为从Python中的循环中的列表中删除元素
while len(tokenList) > 0:
# loop through the tokenList list
# reset the updated token list and the remove flag
updatedTokenList = []
removeFlag = False
for token in tokenList:
completionHash = aciServer.checkTaskForCompletion(token)
# If the completion hash is not the empty hash, parse the information
if completionHash != {}:
# if we find that a task has completed, remove it from the list
if completionHash['Status'] == 'FINISHED' and completionHash['Error'] == '':
# The task completed successfully, remove the token from the list
removeFlag = True
elif completionHash['Status'] == 'RUNNING' and completionHash['Error'] == '':
# The task must still be running
print('Task ' + completionHash['Type'] + ' ' + token + ' has been running for ' + completionHash['Runtime'] + ' seconds.')
elif completionHash['Status'] == 'queued':
# The task is in the queue
print('Task ' + completionHash['Type'] + ' ' + token + ' is queued in position ' + completionHash['QueuePosition'])
elif completionHash['Status'] == 'not_found':
# Did not find a task with this token, possible the task hasn't been added yet
print(completionHash['Error'])
# if the task is still running, no change to the token list will have occured
else:
# This is probably because the server got rid of the token after the task completed
print('Completion hash is empty, something went wrong.')
tokenListError.append(token)
removeFlag = True
if not removeFlag:
print('appending token to updatedTokenList')
updatedTokenList.append(token)
print('length of tokenList after removal loop: ' + str(len(updatedTokenList)))
# wait some time, proportional to the number of tasks left
checkInterval = len(updatedTokenList) * checkIntervalMultiplier
print('Waiting ' + str(checkInterval) + ' seconds before checking again...')
print('Tokens remaining: ' + str(len(updatedTokenList)))
# replace the original token list with the updated token list
tokenList = updatedTokenList
# wait a while based on how many tokens remain
time.sleep(checkInterval)
因此,所有这一切的重点是更新tokenList与新列表。每次循环时,新任务都已完成,不应将其添加到updatedTokenList。剩下的任务令牌将会替换原始的令牌列表。
这不起作用。在我第一次通过时,即使尚未完成任务,它也不会将任何标记添加到updatedTokenList。我无法弄清楚我做错了什么。有什么建议么?
情况就会变得容易得多,如果你移动逻辑到一个函数:
#This function should have a more descriptive name that follows your
#project's API.
def should_keep(token):
"""returns True if the token should be kept"""
#do other stuff here. Possibly print stuff or whatever ...
...
现在,你可以用一个简单的列表理解取代你的列表:
tokenList = [ token for token in tokenList if should_keep(token) ]
需要注意的是我们的避风港” t 实际上取代了列表。旧名单仍然可能有其参考。如果你想尽可能地替换列表,这没有问题。我们只是用切片赋值:
tokenList[:] = [ token for token in tokenList if should_keep(token) ]
一个问题是,在第一次遇到应该删除的令牌后,您从未将removeFlag设置为False。只要它检测到一个应该被删除,它也会从列表中删除所有的令牌。您需要在所有completionHash elifs中将其设置为False(并确保它们测试的状态值是唯一的可能性),或者将它立即设置在您的for token in tokenlist
循环中。
如果在测试中第一个作业你的时间完成第一次检查完成后,将符合描述的行为。
我明白你想删除列表中的项目,而不让他们,所以,我觉得你可以做的是保存对应于您要删除列表中的项目数量。例如,假设我有一个包含1到5的数字的列表,但我只希望这个列表得到奇数,所以我想删除偶数。我要做的是设置一个循环与计数器,检查列表中的每个项目的条件(在这种情况下,我会检查是否myList[ItemNumber] % 2 == 0
),如果它确实,我会将ItemNumber
设置为另一个列表中的项目。然后,当所有要删除的项目在这个新列表中都有他们的号码时,我会调用另一个循环来遍历这个新列表,并从另一个列表中删除那些包含在新列表中的项目。像这样:
myList = [1, 2, 3, 4, 5]
count = 0
toBeDeleted = []
while count < len(myList):
if myList[count] % 2 == 0:
toBeDeleted.append(count)
count += 1
cont2 = len(toBeDeleted)
while cont2 > 0:
cont3 = toBeDeleted[cont2 - 1]
myList.pop(cont3)
cont2 -= 1
这对这个问题很好,所以我相信并希望它能帮助你。
对于初学者,您应该在循环的每次迭代开始时将'removeFlag'重置为'False'。这可能是第一项任务已完成,并且由于'removeFlag'永远不会重置为'False',所以您将删除所有任务。如果这不能解决您的问题,请尝试单步执行代码并查看checkTaskForCompletion()返回的内容,验证您是否拥有正确的if条件。 – acattle 2013-05-03 01:29:51