簡體   English   中英

如何避免“RuntimeError: dictionary changed size during iteration”錯誤?

[英]How to avoid "RuntimeError: dictionary changed size during iteration" error?

我有一個列表字典,其中一些值為空:

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

在創建這些列表的最后,我想在返回我的字典之前刪除這些空列表。 我試着這樣做:

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

但我得到了一個RuntimeError 我知道在遍歷字典時不能添加/刪除字典中的元素……那么有什么辦法解決這個問題呢?


請參閱在迭代 Python dict 時修改它以獲取可能導致問題的引用以及原因。

在 Python 3.x 和 2.x 中,您可以使用list來強制制作密鑰的副本:

for i in list(d):

在 Python 2.x 中,調用keys創建了一個密鑰副本,您可以在修改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]}

(順便說一句 - 通常迭代您的數據結構的副本,而不是使用.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'}

將字典項轉換為 list 會創建其項的列表,因此您可以對其進行迭代並避免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' 與 '.items()' 一起使用,這是一個簡單的示例:

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 循環)字典時刪除。 有多種選擇; 一種簡單的方法是更改​​以下行

for i in x.keys():

for i in list(x)

運行時錯誤的原因是,當數據結構在迭代過程中發生變化時,您無法迭代數據結構。

實現您正在尋找的一種方法是使用 list 來附加您要刪除的鍵,然后在字典上使用 pop 函數在迭代列表時刪除識別的鍵。

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)
dictc={"stName":"asas"}
keys=dictc.keys()
for key in list(keys):
    dictc[key.upper()] ='New value'
print(str(dictc))

對於這樣的情況,我喜歡在修改原始字典時制作一個深層副本並循環遍歷該副本。

如果查找字段在列表中,則可以在列表的for循環中枚舉,然后將位置指定為索引以訪問原始dict中的字段。

如果字典中的值也是唯一的,那么我使用了這個解決方案

        keyToBeDeleted=None
        for k,v in mydict.items():
            if(v==match):
                keyToBeDeleted=k
                break
        mydict.pop(keyToBeDeleted,None)
  • Python “RuntimeError: dictionary changed size during iteration”發生在我們在迭代時改變字典的大小時。

  • 要解決該錯誤,請使用 copy() 方法創建可以迭代的字典的淺表副本,例如my_dict.copy()

my_dict = {'a': 1, 'b': 2, 'c': 3}

for key in my_dict.copy():
    print(key)
    if key == 'b':
        del my_dict[key]

print(my_dict) # 👉️ {'a': 1, 'c': 3}
  • 您還可以將字典的鍵轉換為列表並遍歷鍵列表。
my_dict = {'a': 1, 'b': 2, 'c': 3}

for key in list(my_dict.keys()):
    print(key)
    if key == 'b':
        del my_dict[key]

print(my_dict)  # 👉️ {'a': 1, 'c': 3}

嵌套 null 個值

假設我們有一個帶有嵌套鍵的字典,其中一些是 null 值:

dicti = {
"k0_l0":{
    "k0_l1": {
        "k0_l2": {
                "k0_0":None,
                "k1_1":1,
                "k2_2":2.2
                }
        },
        "k1_l1":None,
        "k2_l1":"not none",
        "k3_l1":[]
    },
    "k1_l0":"l0"
}

然后我們可以使用這個 function 刪除 null 值:

def pop_nested_nulls(dicti):
    for k in list(dicti):
        if isinstance(dicti[k], dict):
            dicti[k] = pop_nested_nulls(dicti[k])
        elif not dicti[k]:
            dicti.pop(k)
    return dicti

Output 用於pop_nested_nulls(dicti)

{'k0_l0': {'k0_l1': {'k0_l2': {'k1_1': 1,
                               'k2_2': 2.2}},
           'k2_l1': 'not '
                    'none'},
 'k1_l0': 'l0'}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM