반복하면서 파이썬의 사전에서 항목을 삭제하는 것이 합법적입니까?
예를 들면 다음과 같습니다.
for k, v in mydict.iteritems():
if k == val:
del mydict[k]
아이디어는 반복되는 사전의 하위 세트 인 새 사전을 작성하는 대신 사전에서 특정 조건을 충족하지 않는 요소를 제거하는 것입니다.
이것이 좋은 해결책입니까? 더 우아하고 효율적인 방법이 있습니까?
반복하면서 파이썬의 사전에서 항목을 삭제하는 것이 합법적입니까?
예를 들면 다음과 같습니다.
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}
for k, v in list(mydict.items()):
에 대한 같은 파이썬 3에서 잘 작동 keys()
되는가 list(keys())
.
RuntimeError: dictionary changed size during iteration
for k in list(mydict.keys()):
하여 keys () 메서드를 반복자로 만들고 반복하는 동안 dict 항목을 삭제할 수 없습니다. list () 호출을 추가하여 keys () 반복자를 목록으로 바꿉니다. 따라서 for 루프 본문에 있으면 더 이상 사전 자체를 반복하지 않습니다.
두 단계로 수행 할 수도 있습니다.
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)
remove
루프 접근 방식이 더 좋습니다.
for k in [k for k in mydict if k == val]: del mydict[k]
반복하는 동안 컬렉션을 수정할 수 없습니다. 그 방법은 광기입니다-가장 눈에 띄게, 현재 항목을 삭제하고 삭제하도록 허용 된 경우 반복자가 (+1) 이동해야하고 다음 호출 next
은 그 이상으로 넘어갈 것입니다 (+2). 한 요소 (삭제 한 요소 바로 뒤에있는 요소)를 건너 뜁니다. 두 가지 옵션이 있습니다.
.keys()
이것을 위해 et al을 사용할 수 있습니다 (Python 3에서는 결과 반복자를에 전달하십시오 list
). 공간적으로 많은 낭비가 될 수 있습니다.mydict
평소와 같이 반복 하여 별도의 컬렉션에서 삭제할 키를 저장합니다 to_delete
. 당신이 반복하는 일을 할 때 mydict
, 모든 항목을 삭제 to_delete
에서 mydict
. 첫 번째 접근 방식에서 일부 (삭제 된 키 수 및 유지 수에 따라) 공간을 절약 할 수 있지만 몇 줄이 더 필요합니다.You can't modify a collection while iterating it.
이 dicts 및 친구를위한 단지 정확하지만 반복하는 동안 목록을 수정할 수 있습니다 :L = [1,2,None,4,5] <\n> for n,x in enumerate(L): <\n\t> if x is None: del L[n]
can't
dict과 친구들에게만 올바른 반면 shouldn't
목록에는 적합합니다.
대신에 반환 된 것과 같은 사본을 반복하십시오 items()
.
for k, v in list(mydict.items()):
del v
직접 사용할 수 없으므로 사용하지 않을 각 v의 사본을 만들었으므로 어쨌든 키로 항목에 액세스해야합니다. dict.keys()
더 나은 선택입니다.
v
삭제 기준 으로 얼마나 많이 사용해야 할 지에 달려 있습니다.
사용하는 것이 가장 깨끗합니다 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에서 작동합니다.
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 )
# {}
먼저 삭제할 키 목록을 작성한 다음 해당 목록을 반복하여 삭제할 수 있습니다.
dict = {'one' : 1, 'two' : 2, 'three' : 3, 'four' : 4}
delete = []
for k,v in dict.items():
if v%2 == 1:
delete.append(k)
for i in delete:
del dict[i]
삭제하려는 항목이 항상 dict 반복의 "시작"에있는 경우 적합한 방법이 있습니다
while mydict:
key, value = next(iter(mydict.items()))
if should_delete(key, value):
del mydict[key]
else:
break
"시작"은 특정 Python 버전 / 구현에 대해서만 일관성이 보장됩니다. 예를 들어 Python 3.7의 새로운 기능
dict 객체의 삽입 순서 보존 특성은 Python 언어 사양의 공식 부분으로 선언되었습니다.
이 방법은 적어도 파이썬 3에서 많은 다른 답변이 제안하는 dict 사본을 피합니다.
Python3에서 위의 솔루션을 시도했지만이 객체를 dict에 객체를 저장할 때 유일하게 작동하는 것 같습니다. 기본적으로 dict () 사본을 만들고 원래 사전의 항목을 삭제하는 동안 반복합니다.
tmpDict = realDict.copy()
for key, value in tmpDict.items():
if value:
del(realDict[key])