如何避免“RuntimeError: dictionary changed size during iteration”;错误呢?

我有一个字典的列表,其中一些值是空的:

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

在创建这些列表的最后,我想在返回字典之前删除这些空列表。我试着这样做:

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

但是我得到了一个RuntimeError。我知道你不能在字典中添加/删除元素,而迭代它…那有什么解决办法呢?


参见在迭代时修改Python字典,以了解这可能导致问题的引用,以及原因。

449798 次浏览

在Python 3中。X和2。x你可以使用use list来强制创建一个键的副本:

for i in list(d):

在Python 2中。调用keys的x复制了一个键,你可以在修改dict时遍历这些键:

for i in d.keys():

但请注意,在Python 3中。x第二种方法对你的错误没有帮助,因为keys返回一个视图对象,而不是将键复制到列表中。

只需使用字典推导式将相关项复制到一个新的词典中:

>>> 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 = {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}

你只需要使用copy:

这样你就可以遍历原来的字典字段,并且可以动态地更改所需的字典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。)

出现运行时错误的原因是,当数据结构在迭代过程中发生变化时,您无法对其进行迭代。

实现您正在寻找的一种方法是使用list来附加您想要删除的键,然后使用dictionary上的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)

对于这种情况,我喜欢做一个深度拷贝,在修改原始字典的同时循环遍历该拷贝。

如果查找字段位于列表中,则可以在列表的for循环中进行枚举,然后将位置指定为索引,以访问原始字典中的字段。

当字典在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)

这招对我很管用:

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

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

避免“迭代时字典改变大小”的错误。

例如:“当你试图删除某个键时”;,

只需使用'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)
< p > + + + 输出:< / p >

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

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

+++

这只是一个例子,根据您的情况/要求更改它,

.

.

如果字典中的值也是唯一的,那么我就使用这个解决方案

        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}