我有一个字符串列表。我正在尝试删除具有某些子字符串的元素。如果我使用以下内容,则只删除包含“Cantab”的元素:
for line in merged:
if 'Duke' in line and 'Sir' not in line or 'Cantab' in line or 'Rick' in line:
merged.remove(line)
如果我尝试分解条件,我的目标结果无法实现,但我成功删除了包含Duke但不包括Sir Duke的元素。:
if 'Duke' in line and 'Sir' not in line:
merged.remove(line)
这可以按预期工作:
if 'Duke' in line and 'Sir' not in line:
merged.remove(line)
elif 'Cantab' in line:
merged.remove(line)
但以下只删除包含'Cantab'的元素!!!:
if 'Duke' in line and 'Sir' not in line:
merged.remove(line)
elif 'Cantab' in line:
merged.remove(line)
elif 'Rick' in line:
merged.remove(line)
我在找出这里的逻辑时遇到了麻烦。谢谢!
答案 0 :(得分:4)
通常,不要迭代列表和同时从列表中删除项目。它会移动尚未迭代的项目的内部索引,因此并非所有项目都会被迭代。
您可以通过循环遍历merged
:
for line in list(merged):
此示例说明了问题:
merged = ['Cantab', 'Duke', 'Cantab', 'Duke', 'Cantab', 'Duke']
for line in merged:
print(line)
if 'Duke' in line and 'Sir' not in line or 'Cantab' in line or 'Rick' in line:
merged.remove(line)
print(merged)
打印
Cantab # only the Cantab lines are being iterated over!
Cantab
Cantab
['Duke', 'Duke', 'Duke']
考虑循环的第一次迭代。当line
等于Cantab
时,第一个Duke
的内部索引为1.但删除Cantab
后,第一个Duke
的内部索引变为0.但Python将循环索引提升为1!现在第二个 Cantab
位于索引1处,因此第一个Duke
被完全跳过。
或者,您可以通过向后迭代列表来修复问题,而无需复制merged
。以这种方式完成,删除merged
中的当前项是安全的,因为尚未修改的项目的位置未被修改:
merged = ['Cantab', 'Duke']*3
for i in range(len(merged)-1, -1, -1):
line = merged[i]
if 'Duke' in line and 'Sir' not in line or 'Cantab' in line or 'Rick' in line:
del merged[i]
print(merged)
打印
[]
根据需要。