Python: Removing list element while iterating over list
本问题已经有最佳答案,请猛点这里访问。
我正在迭代Python中的元素列表,对其执行一些操作,然后在满足某些条件时删除它们。
1 2 3 4 | for element in somelist: do_action(element) if check(element): remove_element_from_list |
我应该用什么来代替删除元素?我也看到过类似的问题,但是请注意,要为所有元素执行的Do-Action部分的存在,从而消除了使用过滤器的解决方案。
您总是可以迭代列表的副本,这样您就可以自由地修改原始列表:
1 2 3 | for item in list(somelist): ... somelist.remove(item) |
要满足这些条件:就地修改原始列表,没有列表副本,只有一次通过,有效,传统的解决方案是向后迭代:
1 2 3 4 5 | for i in xrange(len(somelist) - 1, -1, -1): element = somelist[i] do_action(element) if check(element): del somelist[i] |
好处:在每次迭代中都不执行
更新:如果你想向前迭代,它是可能的,只是更狡猾和更丑陋:
1 2 3 4 5 6 7 8 9 10 | i = 0 n = len(somelist) while i < n: element = somelist[i] do_action(element) if check(element): del somelist[i] n = n - 1 else: i = i + 1 |
清单:
1 | results = [x for x in (do_action(element) for element in somelist) if check(element)] |
您仍然可以使用filter,将元素修改移到外部函数(仅迭代一次)
1 2 3 4 5 6 7 8 9 | def do_the_magic(x): do_action(x) return check(x) # you can get a different filtered list filter(do_the_magic,yourList) # or have it modified in place (as suggested by Steven Rumbalski, see comment) yourList[:] = itertools.ifilter(do_the_magic, yourList) |
1 2 3 | for element in somelist: do_action(element) somelist[:] = (x for x in somelist if not check(x)) |
如果你真的需要一次完成而不复制列表
1 2 3 4 5 6 7 8 | i=0 while i < len(somelist): element = somelist[i] do_action(element) if check(element): del somelist[i] else: i+=1 |
另一种方法是:
1 2 3 4 5 | while i<len(your_list): if #condition : del your_list[i] else: i+=1 |
因此,在检查的同时并排删除元素
您可以生成一个返回所有未删除内容的生成器:
1 2 3 4 5 | def newlist(somelist): for element in somelist: do_action(element) if not check(element): yield element |
不完全到位,但有一些想法:
1 2 3 4 5 6 7 8 9 | a = ['a', 'b'] def inplace(a): c = [] while len(a) > 0: e = a.pop(0) if e == 'b': c.append(e) a.extend(c) |
您可以扩展函数来调用条件中的过滤器。
为什么不重写成
1 2 3 4 5 | for element in somelist: do_action(element) if check(element): remove_element_from_list |
请参阅此问题以了解如何从列表中删除,尽管看起来您已经看到了迭代时从列表中移除项
另一个选择是如果你真的想保持这个不变
1 2 3 4 5 6 | newlist = [] for element in somelist: do_action(element) if not check(element): newlst.append(element) |