2014-11-21 2 views
1

나는 파이썬 코드 조각이있다.이 코드는 루프 몸체가 사전을 바꿀 수있는 사전의 모든 키를 반복 할 필요가있다.변화하는 사전을 반복하다.

사전 반복자를 시도하면 RuntimeError: dictionary changed size during iteration이됩니다. 오류 메시지를 검색하면 another question으로 안내됩니다. 제안 된 솔루션은 반복을 시작하기 전에 키 목록을 복사하는 것입니다.

하지만 원래의 키뿐만 아니라 반복되는 동안 반복되는 키를 반복해야하기 때문에이 시나리오는 부분적인 대답입니다. 사전에 키가 더 이상 추가되지 않으면 종료되는 코드가 필요하며 사전에 이미있는 키를 처리했습니다.

지금까지 나는이 함께 올라와있다 :

processed = set() 
while True: 
    keys = set(dictionary) - processed 
    if not keys: 
     break 
    for k in keys: 
     processed.add(k) 
     # Do something with k 

이러한 접근 방식은 지나치게 복잡하게 보인다. 내가 그것을 단순화 할 수있는 방법이 있습니까, 그리고 여전히 각각의 키를 두 번 이상 처리하지 않고 사전에 추가되는 모든 키를 처리해야합니까? while 루프의 첫 번째 네 줄은 간단하게 기록 된 수있는 몇 가지 다른 언어

: 파이썬에서 작동하지 않습니다 그러나

while keys = set(dictionary) - processed: 

. 나는 파이썬의 while 루프에서 조건으로 할당을 사용하는 것에 대해 a question을 발견했다. 그러나 제안 된 답변 중 어느 것도 내 시나리오에 적용되지 않는 것 같습니다.

답변

0

내 코드를 재 작성 여부를 지정해야합니다 :

processed = set() 
while set(dictionary) - processed: 
    for k in set(dictionary) - processed: 
     processed.add(k) 
     # Do something with k 

이것은 set(dictionary) - processed 표현을 중복 않지만, 여전히 코드를 읽기 쉽게 .

2

반대 방법을 고려하십시오. 이미 처리 된 키가 아닌 처리해야 할 키를 추적하십시오.

remaining = set(dictionary.items()) 

while remaining: 
    key, value = remaining.pop() 

    # process the item 

    if item_to_add: 
     dictionary[new_key] = new_value 
     remaining.add((new_key, new_value)) 

이렇게하면 각 반복마다 값 비싼 설정 차이 작업이 발생하지 않습니다.

처리 중에 어떤 키가 추가되었는지 정말로 알 수 없다면 질문의 코드는 그대로입니다. 다음과 같이 약간 다른 방법으로 작성하십시오.

keys = set(dictionary) 
processed = set() 

while keys: 
    for k in keys: 
     # Do something with k 

    processed.update(keys) 
    keys = set(dictionary) - processed 

더 낫습니까? 보다 나쁜? 당신이 결정할 수 있기를 바랍니다.

+0

내 루프 본문에 명시 적으로 키를 사전에 추가하지 않습니다. 오히려 사전에 키를 추가하거나 추가하지 않을 수도있는 다른 함수를 호출합니다. 따라서 루프의 본문에 어떤 키가 추가되었는지 알 수있는 유일한 방법은 현재 키 세트를 살펴 보는 것입니다. – kasperd

+0

사전을 반복적으로 다시 검사하면 변경된 내용을 확인하는 데 많은 비용이 듭니다. 코드를 리팩토링 할 수있는 방법이 있습니까? 그래서 어떤 항목이 추가되는지 알고 계십니까? 그렇지 않다면 원본 코드가 나에게 잘 어울립니다. –

+0

루프의 본문에 추가되는 내용을 알리려면 코드를 리팩토링하는 것이 실용적이지는 않습니다. 필자의 경우 세트 차이의 성능은 하나의 키를 처리하는 비용이 설정된 차이를 계산하는 비용보다 훨씬 높기 때문에 문제가되지는 않습니다. – kasperd

2

아마 OrderedDict을 사용할 수 있습니다. 반복 중에 키를 추가해도 문제가 없습니다.

>>> from collections import OrderedDict 
>>> d = OrderedDict([(1, 2), (3, 4)]) 
>>> for k in d: 
...  if k == 1:d[5] = 6 
...  print(k) 
... 
1 
3 
5 

키를 업데이트하거나 추가하는 중입니까? 업데이트하는 경우, 당신은 키가 다시 여부를 처리해야

+0

이것은 아마도 더 깨끗한 해결책 일 수 있습니다. 문서에서는 반복을 통해 키가 추가 된 순서대로 처리된다는 내용을 설명합니다. 그러나 iteration이 반복되기 전에 추가 된 키가 반복 처리되기 전에 처리되도록 보장되어 있는지는 명시하지 않습니다. 나는 기존의 키를 변경하지 않고 키를 추가 및 제거 만합니다. – kasperd