2013-05-18 4 views
2

Я хотел бы перебрать набор, пока я удаляю элементов из него. Есть похожие вопросы для deleting one item at the time или для lists, но они не работают для моего дела.Изменение набора во время итерации по нему

Код следует; Я перебираю набор ZN, и в конце итерации я удаляю несколько предметов (принадлежащих набору 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) 
+0

Поскольку ЗН в ** для г в ЗН ** есть ** набор (диапазон (N)) ** .. – matzone

+0

Возможная дубликат [удалять элементы из множества whil e iterating over it] (http://stackoverflow.com/questions/16551334/delete-items-from-a-set-while-iterating-over-it) –

ответ

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 -= 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 
+0

Спасибо! Скопируйте вставляемый код, предложенный мной: 'Синтаксическая ошибка: Cosets.append (list (tmp))' – geo909

+0

@ geo909: Какая версия Python? Я использовал множество понятий, которые доступны только в Python 2.7 и Python 3.x. –

+0

Честно говоря, я использую sage (интерфейс браузера «ноутбук», доступ к мудрецу моего университета через мой браузер), где вы по существу кодируете в python с дополнительными математическими библиотеками (я думаю, я совершенно новичок в кодировании и этом). Я вижу, что версия sage - 4.3 (декабрь 2009), но для ее жизни я не могу найти способ получить версию python через интерфейс ноутбука. С другой стороны, я немного изменил код, чтобы он работал для меня, я обновлю вопрос. – geo909