【问题标题】:Remove elements as you traverse a list in Python [duplicate]在Python中遍历列表时删除元素[重复]
【发布时间】:2010-11-24 02:02:01
【问题描述】:

在 Java 中,我可以使用 Iterator 然后使用迭代器的 .remove() 方法删除迭代器返回的最后一个元素,如下所示:

import java.util.*;

public class ConcurrentMod {
    public static void main(String[] args) {
        List<String> colors = new ArrayList<String>(Arrays.asList("red", "green", "blue", "purple"));
        for (Iterator<String> it = colors.iterator(); it.hasNext(); ) {
            String color = it.next();
            System.out.println(color);
            if (color.equals("green"))
                it.remove();
        }
        System.out.println("At the end, colors = " + colors);
    }
}

/* Outputs:
red
green
blue
purple
At the end, colors = [red, blue, purple]
*/

我将如何在 Python 中执行此操作?在 for 循环中迭代列表时,我无法修改列表,因为它会导致内容被跳过(请参阅 here)。而且似乎没有与 Java 的 Iterator 接口等效的东西。

【问题讨论】:

标签: python list loops iterator python-datamodel


【解决方案1】:

Python 中最好的方法是创建一个新列表,最好是在 listcomp 中,将其设置为旧列表的 [:],例如:

colors[:] = [c for c in colors if c != 'green']

不是colors =,正如一些答案所暗示的那样——它只会重新绑定名称,最终会留下一些对旧“body”的引用; colors[:] = 在所有方面都好得多;-)。

【讨论】:

  • 列表理解是最好的选择。
  • 或 colors=list(c for c in colors if c != 'green')
  • @dugres:不完全是:colors = list(...) 确实重新绑定。 Alex 坚持认为最好不要将无用的列表留在内存中。
  • @Devin,不只是为了其他参考。例如。如果颜色是全局的,则在函数中执行colors= 需要额外的global colorscolors[:]= 不需要。旧列表的 GC 不会在所有版本的 Python 中立即发生。等等:分配给name[:] 从来没有任何不利之处,分配给name 经常有许多不利之处(包括偶尔出现的令人费解的错误,即“很少对你来说”的情况确实发生但你习惯了错误的方式),所以对于正确的方法name[:]= 和针对错误的方法name=,这是一种隐藏。只有一种明显的方式...
  • ...虽然这可能并不明显,除非你是荷兰人;-)。
【解决方案2】:

遍历列表的副本

for c in colors[:]:
    if c == 'green':
        colors.remove(c)

【讨论】:

  • 为什么使用颜色[:]而不是颜色?
  • colors[:] 是一个副本(list(colors) 的拼写很奇怪,但是,叹息,惯用的方式)所以它不会受到.remove 调用的影响。
  • 将其称为更惯用的唯一原因是 stdlib 复制模块文档引用了它。尽管如此,我仍然会使用 list(otherlist) 来复制(或者可能是 copy.copy(otherthing))
【解决方案3】:

你可以使用过滤功能:

>>> colors=['red', 'green', 'blue', 'purple']
>>> filter(lambda color: color != 'green', colors)
['red', 'blue', 'purple']
>>>

【讨论】:

    【解决方案4】:

    或者你也可以这样做

    >>> colors = ['red', 'green', 'blue', 'purple']
    >>> if colors.__contains__('green'):
    ...     colors.remove('green')
    

    【讨论】:

    • 使用.__contains__() 比使用'green' in colors 没有优势
    • 另外,colors.remove() 只删除了 first 的出现,而不是所有的出现。
    • 可以通过以下方式使解决方案起作用: while 'green' in colors: colors.remove('green') 。当然,这是 O(n**2),而更好的解决方案是 O(n)。
    猜你喜欢
    • 2019-10-16
    • 2013-08-05
    • 2012-12-05
    • 2011-10-31
    • 2017-02-08
    • 2014-04-12
    • 2012-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多