2012-12-13 4 views
0

타임 스탬프가있는 사전이 있는데이를 반복하고 오래된 것으로 간주되는 항목을 제거하려고합니다 (파이썬에서) 어떻게하면됩니까? 이 코드는 나에게 RuntimeError에 있습니다 : 사전이 반복 동안 크기를 변경 : 그 반복하면서사전에서 반복되는 항목을 제거하는 방법은 무엇입니까?

for key, value in img_dict.iteritems() : 
     if (time.time()-float(img_dict[key])) >= stale_img: 
      logger.debug('STALE IMAGE FROM '+hexlify(key)+ ' - GOT CLOSED NOW!') 
      del img_dict[key] 
      data_upload = True 
+1

시도'img_dict.items()' – JBernardo

+2

이 문제가 아니라 왜 당신은() img_dict.iteritems에, 키 '값을 사용하는'대신'img_dict에서 키에 대한' 'value '를 어디에도 사용하지 않고 실제로'img_dict [key]'를 명시 적으로 수행하고 있다는 것을 감안할 때? – abarnert

답변

4

당신은 컬렉션을 수정할 수 없습니다. 이 작업을 수행해야하는 경우

  • (0)를 참조하기 위해 디자인을 다시 생각 :

    이 주위에 몇 가지 방법이 있습니다.

  • (1) 컬렉션을 수정하지 마십시오. 대신 필터링 된 새 컬렉션을 작성하십시오.
  • (2) 컬렉션을 반복하지 마십시오. 대신 컬렉션 복사본을 반복합니다.
  • (2.5) 사전의 경우 키 복사본을 반복하고 명시 적으로 값을 가져옵니다.

값을 반복해서 처리 했음에도 불구하고 값을 명시 적으로 가져오고 있으므로 여기에 # 2로 갈 이유가 없습니다.

new_img_dict = {} 
for key in img_dict: 
    if (time.time()-float(img_dict[key])) >= stale_img: 
     logger.debug('STALE IMAGE FROM '+hexlify(key)+ ' - GOT CLOSED NOW!') 
     data_upload = True 
    else: 
     new_img_dict[key] = img_dict[key] 
img_dict = new_img_dict 

또는 :

여기에 다른 두 사람의 구현입니다

for key in img_dict.keys(): 
    if (time.time()-float(img_dict[key])) >= stale_img: 
     logger.debug('STALE IMAGE FROM '+hexlify(key)+ ' - GOT CLOSED NOW!') 
     del img_dict[key] 
     data_upload = True 

(당신이, img_dict.keys() 대신, 파이썬 3 호환 img_dict.keys()[:]을 수행합니다.)

두 가지 중에서 어떻게 선택합니까?

일반적으로 첫 번째 이유는 일반적으로 추론하기가 쉽지만 일반적으로 변경 불가능한 개체와 순수한 연산은 쉽게 추론 할 수 있습니다. 예를 들어 어딘가에서 예외를 throw하면 img_dict은 항상 중간 버전이 아닌 원래 버전 또는 완성 된 버전을 갖습니다. 그리고 물론 그것을 반복하면서 뭔가를 바꾸는 것이 무엇을 의미하는지 생각할 필요가 없습니다. 그러나 일부 드문 경우에는 "foo"알고리즘을 "foo"가 아닌 "copy foo"알고리즘으로 변환하는 것이 어렵습니다.

첫번째는, 팩터는

용 등의 별도 기능을 꺼내, 이해력 (또는 filter 등 고차 함수 호출)으로 재기록 발전기로 전환하는 것이 일반적으로 더 쉽다 성능을 향상 시키려면 첫 번째 값은 일반적으로 더 빠르며 많은 값을 필터링하는 경우 메모리를 적게 사용하는 반면, 대부분의 값을 유지하는 경우 두 번째 값은 일반적으로 더 좋습니다. (컷오프는 서로 다른 컬렉션 유형에 따라 다릅니다. 일반적으로 중요하지 않으며, 그렇다면 두 가지 방법으로 모두 작성해야합니다.)

이 경우에 적용될 수 있습니다. . 너는 너무 오래 되었는지를보기 위해 모든 열쇠를 걷고있다. 정렬 된 목록이나 우선 순위 대기열을 사용했다면 그렇게하지 않아도됩니다. 이제 컬렉션을 이전 값을 플러시해야하는 것보다 더 자주 dict으로 사용해야하는 경우 데이터 구조 변경의 이점보다 많은 비용이 발생할 것입니다. 하지만 둘 다 가지고 있지 않은 이유는 무엇입니까?

stale_time = time.time() - stale_img 
for key in itertools.takewhile(lambda key: float(key) < stale_time, 
           img_sorted_key_list): 
    del img_dict[key] 

그리고 당신은 포장 수 : 또는, 더 간단하게

for key in img_sorted_key_list: 
    if time.time() - float(key) > stale_img: 
     break 
    del img_dict[key] 

을 : 당신이 값으로 사전 매핑 키의 상단에 키의 정렬 된 목록을 가지고 있다면, 당신은이 작업을 수행 할 수 정렬 된 키 목록과 함께 좋은 Cache 클래스 또는 무언가로 사전.

1

이 예제를 살펴보십시오. 아마도 도움이 될 것입니다. 목록이나 사전의 요소를 끝에서부터 삭제할 때 기억하십시오. iteritems() 메소드를 사용하지 마십시오.

keysMap = [ 
     {"key": 1 }, 
     {"key" : 2 }, 
     {"key" : 3 }, 
     {"key" : 4 }, 
     {"key" : 5 }, 
     {"key" : 6 } 
     ] 
i=len(keysMap)-1 
while i > 0 : 
    key = keysMap[i] 
    if key["key"]==2 : 
     del(keysMap[i]) 
    i=i-1 

# Printing the object data after deleting element key=2  
while i < len(keysMap) : 
    key = keysMap[i] 
    print key 
    i=i+1 
관련 문제