반복하면서 파이썬의 사전에서 항목을 삭제하는 것이 합법적입니까?
예를 들면 다음과 같습니다.
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 )
# {}
