2011-12-17 56 views
8

我基本需要的是检查列表中的每个元素,如果符合某些条件,我想从列表中删除它。如何从循环内正确修改python循环的迭代器

因此,例如,让我们说,

名单= [ '一', 'B', 'C', 'd', 'E']

我基本上想写(原则和而不是我尝试实施的实际代码)

如果列表中的某个元素是'b'或'c',请将其从列表中移除,然后执行下一步。

但是

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

失败,因为“B”时被去除环路采用“d”而不是“C”作为下一个元素。那么有没有办法做到这一点比将元素存储在单独的列表中并在之后将其删除?

谢谢。

回答

9

更简单的方法是使用列表的副本 - 它可以与延伸“从一开始”以列表的“结束”,像这样的切片来完成:

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 
+0

jsbueno非常感谢你。我不觉得有点惭愧。再次感谢! – tst 2011-12-17 12:04:03

+0

我其实想要一个循环内的循环,你的最后一个例子是完美的。再次感谢。 – tst 2011-12-17 12:54:53

1

如果您没有问题创造你可以做列表的副本它是这样的(list comprehension):

[s for s in list if s != 'b' and s != 'c'] 
8

最好不要重塑已经可用的东西。在这些情况下使用filter函数和lambda。它更pythonic和看起来更干净。

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']] 
+0

实际上,第二个例子中的列表理解比过滤器和lambda组合更“Pythonic”。 – jsbueno 2011-12-17 12:16:27

+0

谢谢,但我需要把一个这样的循环放入另一个环境,这样事情会变得非常混乱。 – tst 2011-12-17 12:54:09

3

这正是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'])]