programing

"RuntimeError: 반복 중 사전 크기 변경" 오류를 방지하는 방법

nicegoodjob 2023. 1. 16. 20:19
반응형

"RuntimeError: 반복 중 사전 크기 변경" 오류를 방지하는 방법

같은 에러의 다른 질문도 모두 확인했지만, 도움이 되는 해결책은 없었습니다=/

목록 사전이 있습니다.

d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}

일부 값이 비어 있는 경우.이러한 목록을 만든 후 사전을 반환하기 전에 빈 목록을 삭제하려고 합니다.현재 다음과 같이 시도하고 있습니다.

for i in d:
    if not d[i]:
        d.pop(i)

하지만 이로 인해 런타임 오류가 발생합니다.사전에서 반복하는 동안에는 사전의 요소를 추가하거나 제거할 수 없습니다.그럼 이 문제를 해결할 방법이 뭘까요?


Python dict를 반복해서 수정하면 문제가 발생할 수 있으며 그 이유는 무엇입니까?를 참조하십시오.

Python 3.x 및 2.x에서는 다음과 같이 사용하여 키의 복사본을 강제로 만들 수 있습니다.

for i in list(d):

Python 2.x에서 호출은 키를 수정하는 동안 반복할 수 있는 복사본을 만들었습니다.dict:

for i in d.keys():

그러나 Python 3.x에서는 이 두 번째 방법은 오류에 도움이 되지 않습니다.keys를 목록으로 복사하는 대신 뷰 개체를 반환합니다.

사용만 하면 됩니다.copy:

이렇게 하면 원래 사전 필드에 반복하여 원하는 dict를 즉시 변경할 수 있습니다.d각 Python 버전에서 동작하기 때문에 더 선명합니다.

In [1]: d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}

In [2]: for i in d.copy():
   ...:     if not d[i]:
   ...:         d.pop(i)
   ...:         

In [3]: d
Out[3]: {'a': [1], 'b': [1, 2]}

(BTW - 일반적으로 데이터 구조 복사를 반복하는 대신.copy사전 또는 슬라이싱용[:]리스트의 경우,import copy->copy.copy(에 상당하는 얕은 복사용)copy사전 또는 슬라이싱으로 뒷받침되는[:]리스트에서 지원되는 것) 또는copy.deepcopy를 참조해 주세요).

사전 이해를 사용하여 관련 항목을 새 딕트에 복사하십시오.

>>> d
{'a': [1], 'c': [], 'b': [1, 2], 'd': []}
>>> d = {k: v for k, v in d.items() if v}
>>> d
{'a': [1], 'b': [1, 2]}

Python 2의 경우:

>>> d
{'a': [1], 'c': [], 'b': [1, 2], 'd': []}
>>> d = {k: v for k, v in d.iteritems() if v}
>>> d
{'a': [1], 'b': [1, 2]}

이 방법은 효과가 있었습니다.

d = {1: 'a', 2: '', 3: 'b', 4: '', 5: '', 6: 'c'}
for key, value in list(d.items()):
    if value == '':
        del d[key]
print(d)
# {1: 'a', 3: 'b', 6: 'c'}

목록으로 사전 항목을 캐스팅하면 해당 항목의 목록이 생성되므로 반복할 수 있으며, 이 작업을 반복하지 않아도 됩니다.RuntimeError.

처음부터 빈 목록을 삽입하는 것을 피하려고 합니다만, 일반적으로 다음과 같이 사용합니다.

d = {k: v for k,v in d.iteritems() if v} # re-bind to non-empty

2.7 이전인 경우:

d = dict( (k, v) for k,v in d.iteritems() if v )

또는 그냥:

empty_key_vals = list(k for k in k,v in d.iteritems() if v)
for k in empty_key_vals:
    del[k]

Python 3의 경우:

{k:v for k,v in d.items() if v}

"반복 오류 중 크기가 변경된 기본"을 방지하기 위해 사용합니다.

예: "일부 키를 삭제하려고 할 때",

'list'와 '.timeout()'을 함께 사용하면 됩니다.다음은 간단한 예를 제시하겠습니다.

my_dict = {
    'k1':1,
    'k2':2,
    'k3':3,
    'k4':4
 
    }
    
print(my_dict)

for key, val in list(my_dict.items()):
    if val == 2 or val == 4:
        my_dict.pop(key)

print(my_dict)

+++ 출력:

{'k1': 1, 'k2': 2, 'k3': 3, 'k4': 4}

{'k1': 1, 'k3': 3

+++

이것은 단지 예에 불과하고, 당신의 사례/요건에 따라 변경해 주십시오.이것이 도움이 되었으면 합니다.

for 루프 중에 사전이 변경되는 동안에는 사전을 반복할 수 없습니다.목록에 캐스팅을 하고 그 목록을 반복하면, 내겐 효과가 있어.

    for key in list(d):
        if not d[key]: 
            d.pop(key)

Python 3은 사전을 반복하는 동안(위의 루프에 사용) 삭제를 허용하지 않습니다.다양한 방법이 있습니다.한 가지 간단한 방법은 다음 행을 변경하는 것입니다.

for i in x.keys():

와 함께

for i in list(x)

런타임 오류가 발생하는 이유는 반복 중에 구조가 변경되는 동안 데이터 구조를 반복할 수 없기 때문입니다.

원하는 것을 얻기 위한 한 가지 방법은 목록을 사용하여 제거할 키를 추가한 다음 사전에서 팝 기능을 사용하여 목록을 반복하는 동안 식별된 키를 제거하는 것입니다.

d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}
pop_list = []

for i in d:
        if not d[i]:
                pop_list.append(i)

for x in pop_list:
        d.pop(x)
print (d)

이런 경우, 나는 원본 dict를 수정하면서 깊이 복사하고 그 복사본을 반복하는 것을 좋아한다.

룩업 필드가 목록 내에 있는 경우 목록의 for 루프에 열거한 후 위치를 인덱스로 지정하여 원래 dict 필드에 액세스할 수 있습니다.

dictc={"stName":"asas"}
keys=dictc.keys()
for key in list(keys):
    dictc[key.upper()] ='New value'
print(str(dictc))

언급URL : https://stackoverflow.com/questions/11941817/how-to-avoid-runtimeerror-dictionary-changed-size-during-iteration-error

반응형