반복하면서 파이썬의 사전에서 항목을 삭제하는 것이 합법적입니까?
예를 들면 다음과 같습니다.
for k, v in mydict.iteritems():
if k == val:
del mydict[k]
아이디어는 반복되는 사전의 하위 세트 인 새 사전을 작성하는 대신 사전에서 특정 조건을 충족하지 않는 요소를 제거하는 것입니다.
이것이 좋은 해결책입니까? 더 우아하고 효율적인 방법이 있습니까?
답변
편집하다:
이 답변은 Python3에서는 작동하지 않으며을 제공합니다 RuntimeError
.
RuntimeError : 반복하는 동안 사전 크기가 변경되었습니다.
mydict.keys()
목록이 아닌 반복자를 반환 하기 때문에 발생 합니다. 의견에서 지적했듯이 간단히 mydict.keys()
목록으로 변환 하면 list(mydict.keys())
작동합니다.
콘솔의 간단한 테스트는 사전을 반복하는 동안 사전을 수정할 수 없음을 보여줍니다.
>>> mydict = {'one': 1, 'two': 2, 'three': 3, 'four': 4}
>>> for k, v in mydict.iteritems():
... if k == 'two':
... del mydict[k]
...
------------------------------------------------------------
Traceback (most recent call last):
File "<ipython console>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
delnan의 답변에서 언급했듯이 항목을 삭제하면 반복자가 다음 항목으로 이동하려고 할 때 문제가 발생합니다. 대신, keys()
메소드를 사용하여 키 목록을 가져 와서 작업하십시오.
>>> for k in mydict.keys():
... if k == 'two':
... del mydict[k]
...
>>> mydict
{'four': 4, 'three': 3, 'one': 1}
items 값을 기준으로 삭제 해야하는 경우 items()
대신 메소드를 사용하십시오 .
>>> for k, v in mydict.items():
... if v == 3:
... del mydict[k]
...
>>> mydict
{'four': 4, 'one': 1}
답변
두 단계로 수행 할 수도 있습니다.
remove = [k for k in mydict if k == val]
for k in remove: del mydict[k]
내가 가장 좋아하는 접근법은 일반적으로 새로운 전략을 만드는 것입니다.
# Python 2.7 and 3.x
mydict = { k:v for k,v in mydict.items() if k!=val }
# before Python 2.7
mydict = dict((k,v) for k,v in mydict.iteritems() if k!=val)
답변
반복하는 동안 컬렉션을 수정할 수 없습니다. 그 방법은 광기입니다-가장 눈에 띄게, 현재 항목을 삭제하고 삭제하도록 허용 된 경우 반복자가 (+1) 이동해야하고 다음 호출 next
은 그 이상으로 넘어갈 것입니다 (+2). 한 요소 (삭제 한 요소 바로 뒤에있는 요소)를 건너 뜁니다. 두 가지 옵션이 있습니다.
- 모든 키 (또는 필요한 것에 따라 값 또는 둘 다)를 복사 한 다음 반복하십시오.
.keys()
이것을 위해 et al을 사용할 수 있습니다 (Python 3에서는 결과 반복자를에 전달하십시오list
). 공간적으로 많은 낭비가 될 수 있습니다. mydict
평소와 같이 반복 하여 별도의 컬렉션에서 삭제할 키를 저장합니다to_delete
. 당신이 반복하는 일을 할 때mydict
, 모든 항목을 삭제to_delete
에서mydict
. 첫 번째 접근 방식에서 일부 (삭제 된 키 수 및 유지 수에 따라) 공간을 절약 할 수 있지만 몇 줄이 더 필요합니다.
답변
대신에 반환 된 것과 같은 사본을 반복하십시오 items()
.
for k, v in list(mydict.items()):
답변
사용하는 것이 가장 깨끗합니다 list(mydict)
.
>>> mydict = {'one': 1, 'two': 2, 'three': 3, 'four': 4}
>>> for k in list(mydict):
... if k == 'three':
... del mydict[k]
...
>>> mydict
{'four': 4, 'two': 2, 'one': 1}
이것은 목록의 병렬 구조에 해당합니다.
>>> mylist = ['one', 'two', 'three', 'four']
>>> for k in list(mylist): # or mylist[:]
... if k == 'three':
... mylist.remove(k)
...
>>> mylist
['one', 'two', 'four']
둘 다 python2와 python3에서 작동합니다.
답변
사전 이해력을 사용할 수 있습니다.
d = {k:d[k] for k in d if d[k] != val}
답변
python3을 사용하면 dic.keys ()를 반복하면 사전 크기 오류가 발생합니다. 이 대체 방법을 사용할 수 있습니다.
python3으로 테스트 한 결과 제대로 작동하고 ” 반복 중 크기가 변경된 사전 “오류 가 발생하지 않습니다.
my_dic = { 1:10, 2:20, 3:30 }
# Is important here to cast because ".keys()" method returns a dict_keys object.
key_list = list( my_dic.keys() )
# Iterate on the list:
for k in key_list:
print(key_list)
print(my_dic)
del( my_dic[k] )
print( my_dic )
# {}