如何从循环内正确修改python中循环的迭代器

2024-04-24 16:12:58 发布

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

我基本上需要检查列表中的每个元素,如果符合某些条件,我想将其从列表中删除。

比如说

list=['a','b','c','d','e']

我基本上想写(原则上不是我试图实现的实际代码)

如果列表中的某个元素是“b”或“c”,请将其从列表中删除并获取下一个元素。

但是

for s in list:
    if s=='b' or s=='c':
        list.remove(s)

失败,因为删除“b”时,循环将“d”而不是“c”作为下一个元素。那么,有没有一种方法比将元素存储在单独的列表中并在之后删除它们更快呢?

谢谢。


Tags: or方法代码in元素列表forif
3条回答

最好不要重新投资已经存在的东西。在这些情况下使用filter函数和lambda。它更像Python,看起来更干净。

filter(lambda x:x not in ['b','c'],['a','b','c','d','e'])

或者你可以使用列表理解

[x for x in ['a','b','c','d','e'] if x not in ['b','c']]

更简单的方法是使用列表的副本-可以使用一个从列表的“开始”扩展到“结束”的片段来完成,如下所示:

for s in list[:]:
    if s=='b' or s=='c':
        list.remove(s)

你已经考虑过这一点,这一点在你的代码中已经足够简单了,除非这个列表非常大,并且在代码的关键部分(比如,在动作游戏的主循环中)。在这种情况下,我有时会使用以下成语:

to_remove = []
for index, s in enumerate(list):
    if s == "b" or s == "c":
         to_remove.append(index)

for index in reversed(to_remove):
    del list[index]

当然,您可以使用while循环来代替:

index = 0
while index < len(list):
   if s == "b" or s == "c":
       del list[index]
       continue
   index += 1

这正是itertools.ifilter的设计目标。

from itertools import ifilter

ifilter(lambda x: x not in ['b', 'c'], ['a', 'b', 'c', 'd', 'e'])

会给你一个列表生成器。如果实际需要列表,可以使用将生成器转换为列表的标准技术之一创建它:

list(ifilter(lambda x: x not in ['b', 'c'], ['a', 'b', 'c', 'd', 'e']))

或者

[x for x in ifilter(lambda x: x not in ['b', 'c'], ['a', 'b', 'c', 'd', 'e'])]

相关问题 更多 >