Используйте 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 -= tmp
или ZN.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
Поскольку ЗН в ** для г в ЗН ** есть ** набор (диапазон (N)) ** .. – matzone
Возможная дубликат [удалять элементы из множества whil e iterating over it] (http://stackoverflow.com/questions/16551334/delete-items-from-a-set-while-iterating-over-it) –