2

我想在从中删除项目时迭代一个集合。当时删除一项列表有类似的问题,但它们不适用于我的情况。

代码如下;我迭代了一个集合ZN,在迭代结束时,我删除了一些项目(属于 set 的项目temp)。但迭代仍在“原始”ZN 上进行。

如何在迭代时修改此代码以更改集合 ZN?

def CyclotomicCosets(q,n):
    N=q^n-1
    ZN=set(range(N))
    Cosets=[]
    for i in ZN:
        tmp=set([])
        for j in range(n):
            tmp.add( i*(q^j) %N)
        Cosets.append(list(tmp))
        ZN=ZN.difference(tmp) # <------------ Does not do what I want
    return(Cosets)
4

1 回答 1

1

使用while循环和.pop()值从集合中处理:

def CyclotomicCosets(q, n):
    N = q ^ n - 1
    ZN = set(range(N))
    Cosets = []
    while ZN:
        i = ZN.pop()
        tmp = {i * (q ^ j) % N for j in range(n)}
        Cosets.append(list(tmp))
        ZN -= tmp
    return Cosets

请注意,我用for集合理解替换了您的内部循环,以使其更快更紧凑。这些是在 Python 2.7 和 Python 3 中引入的,在早期版本的 python 中,您可以使用生成器表达式:

tmp = set(i * (q ^ j) % N for j in range(n))

您最初的错误是替换 ZN而不是更新它:

ZN=ZN.difference(tmp)

这并没有改变您在for循环中使用的原始集。相反,您正在创建一个集合并将ZN引用指向该集合。

但是,您不能set在迭代时修改它,因此即使是就地差异也行不通;您将不得不使用ZN -= tmporZN.difference_update(tmp)但这会导致异常:

>>> ZN = set(range(3))
>>> for i in ZN:
...     ZN -= set([2])
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: Set changed size during iteration

更正后的代码给出:

>>> CyclotomicCosets(3, 5)
[[0], [0, 1, 2, 3], [0, 1, 4, 5], [0, 4, 5, 6]]

或者,改为循环range(N),并保留一组您已经处理过的值:

def CyclotomicCosets(q, n):
    N = q ^ n - 1
    Cosets = []
    seen = set()
    for i in range(N):
        if i in seen: continue
        tmp = {i * (q ^ j) % N for j in range(n)}
        Cosets.append(list(tmp))
        seen |= tmp
    return Cosets
于 2013-05-18T15:38:55.210 回答