반복하면서 파이썬의 사전에서 항목을 삭제하는 것이 합법적입니까?
예를 들면 다음과 같습니다.
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'tdict과 친구들에게만 올바른 반면 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])