【问题标题】:delete items from a set while iterating over it迭代时从集合中删除项目
【发布时间】:2013-05-14 19:30:09
【问题描述】:

我有一个集合 myset,我有一个函数可以迭代它以对其项目执行一些操作,这个操作最终会从集合中删除项目。

显然,我不能在迭代原始集合的同时做到这一点。但是,我可以这样做:

mylist = list(myset)
for item in mylist:
    # do sth

有没有更好的办法?

【问题讨论】:

  • 该操作是总是删除项目,还是只有时?如果你总是删除项目,在迭代完成后清空集合可能会更容易。

标签: python python-2.7 set


【解决方案1】:

首先,使用一个集合,就像零比雷埃夫斯告诉我们的,你可以

myset = set([3,4,5,6,2])
while myset:
    myset.pop()
    print(myset)

我添加了一个print 方法来提供这些输出

>>> 
set([3, 4, 5, 6])
set([4, 5, 6])
set([5, 6])
set([6])
set([])

如果您想坚持您对列表的选择,我建议您使用列表推导深复制列表,然后循环遍历副本,同时从原始列表中删除项目。在我的示例中,我会在每个循环中减少原始列表的长度。

l = list(myset)
l_copy = [x for x in l]
for k in l_copy:
    l = l[1:]
    print(l)

给予

>>> 
[3, 4, 5, 6]
[4, 5, 6]
[5, 6]
[6]
[]

【讨论】:

    【解决方案2】:

    这应该可以工作:

    while myset:
        item = myset.pop()
        # do something
    

    或者,如果您需要有条件地删除项目:

    def test(item):
        return item != "foo"  # or whatever
    
    myset = set(filter(test, myset))
    

    【讨论】:

    • 如果我只想从集合中删除所有内容,这很有效。就我而言,我需要掌握每个项目,并在 将其从集合中删除之前对其应用一个函数。
    • @skyork 在您迭代它们时从可迭代对象中删除项目是一个坏主意(如果它解决了您正在做的事情,Python 会引发异常)。你最好建造一套新的,然后把旧的扔掉。
    • "在迭代它们时从可迭代对象中删除项目是一个坏主意(糟糕到 Python 会在你正在做的事情时引发异常)——这是一个常见的误解,但不正确. 对于某些可迭代对象(特别是基于哈希表的),这是不合法的(注意:不是“一个坏主意”),Python 会在您尝试时通知您。对于其他可迭代对象,它是完全有效的,一旦您理解它是如何工作的,可预测的。
    • @kindall “如果实现难以解释,那就是个坏主意”(另外,“可读性很重要”和“美胜于丑”)。是的,对于某些可迭代对象,有一些技巧,例如反向迭代。但仅仅因为你可以,并不意味着你应该。
    • @ZeroPiraeus 有更好的方法来做到这一点(如果你有记忆,创建一个新列表通常会更快)但这并不意味着以另一种方式做是“一个坏主意。 "
    【解决方案3】:

    让我们在修改当前集合时返回所有偶数。

    myset = set(range(1,5))
    myset = filter(lambda x:x%2==0, myset)
    print myset
    

    会回来

    >>> [2, 4]
    

    如果有机会,请使用始终使用lambda,它会让您的生活更轻松。

    【讨论】:

    • 我不同意lambda 总是让你的生活更轻松......实际上,它似乎通常不会让你的生活更轻松。 . .
    【解决方案4】:

    另一种方式可能是:

    s=set()
    s.add(1)
    s.add(2)
    s.add(3)
    s.add(4)
    while len(s)>0:
        v=next(iter(s))
        s.remove(v)
    

    【讨论】:

    • 我不明白这是如何回答这个问题的?
    • 现在可能是有道理的:D..编辑时失去连接。
    • 这与@zero-piraeus 的建议基本相同,只是速度较慢。
    【解决方案5】:

    使用copy 库制作集合的副本,迭代副本并从原始副本中删除。如果您想坚持使用for 循环并且只想迭代一个元素一次 - 如果您不一定要删除所有元素,则可以派上用场。

    import copy
    for item in copy.copy(myset):
        myset.remove(item)
    

    【讨论】:

    • 这是真正的答案。不过,您无需求助于copy。在 Python 中,for item in set(myset): ... 创建了集合的副本。
    猜你喜欢
    • 1970-01-01
    • 2010-12-13
    • 2011-03-03
    • 2012-05-13
    • 2017-05-15
    相关资源
    最近更新 更多