简体   繁体   English

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

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

I have a dictionary of lists in which some of the values are empty:我有一个列表字典,其中一些值为空:

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

At the end of creating these lists, I want to remove these empty lists before returning my dictionary.在创建这些列表的最后,我想在返回我的字典之前删除这些空列表。 I tried doing it like this:我试着这样做:

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

but I got a RuntimeError .但我得到了一个RuntimeError I am aware that you cannot add/remove elements in a dictionary while iterating through it...what would be a way around this then?我知道在遍历字典时不能添加/删除字典中的元素……那么有什么办法解决这个问题呢?


See Modifying a Python dict while iterating over it for citations that this can cause problems, and why.请参阅在迭代 Python dict 时修改它以获取可能导致问题的引用以及原因。

In Python 3.x and 2.x you can use use list to force a copy of the keys to be made:在 Python 3.x 和 2.x 中,您可以使用list来强制制作密钥的副本:

for i in list(d):

In Python 2.x callingkeys made a copy of the keys that you could iterate over while modifying the dict :在 Python 2.x 中,调用keys创建了一个密钥副本,您可以在修改dict时对其进行迭代:

for i in d.keys():

But note that in Python 3.x this second method doesn't help with your error because keys returns an a view object instead of copynig the keys into a list.但请注意,在 Python 3.x 中,第二种方法对您的错误没有帮助,因为keys返回一个视图对象,而不是将键复制到列表中。

You only need to use copy :您只需要使用copy

This way you iterate over the original dictionary fields and on the fly can change the desired dict d .这样,您可以遍历原始字典字段,并且可以动态更改所需的 dict d It works on each Python version, so it's more clear.它适用于每个 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 - Generally to iterate over copy of your data structure, instead of using .copy for dictionaries or slicing [:] for lists, you can use import copy -> copy.copy (for shallow copy which is equivalent to copy that is supported by dictionaries or slicing [:] that is supported by lists) or copy.deepcopy on your data structure.) (顺便说一句 - 通常迭代您的数据结构的副本,而不是使用.copy用于字典或切片[:]用于列表,您可以使用import copy -> copy.copy (对于浅拷贝,相当于受支持的copy通过列表支持的字典或切片[:] )或您的数据结构上的copy.deepcopy 。)

Just use dictionary comprehension to copy the relevant items into a new dict:只需使用字典理解将相关项目复制到新字典中:

>>> 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]}

For this in Python 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]}

This worked for me:这对我有用:

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'}

Casting the dictionary items to list creates a list of its items, so you can iterate over it and avoid the RuntimeError .将字典项转换为 list 会创建其项的列表,因此您可以对其进行迭代并避免RuntimeError

I would try to avoid inserting empty lists in the first place, but, would generally use:我会尽量避免首先插入空列表,但是,通常会使用:

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

If prior to 2.7:如果在 2.7 之前:

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

or just:要不就:

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}

to avoid "dictionary changed size during iteration error".以避免“迭代错误期间字典更改大小”。

for example : "when you try to delete some key" ,例如:“当您尝试删除某个键时”,

just use 'list' with '.items()' , and here is a simple example :只需将 '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)

+++ output : +++ 输出:

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

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

+++ +++

this is just example and change it based on your case/requirements, i hope this helpful.这只是示例,并根据您的案例/要求进行更改,我希望这会有所帮助。

You cannot iterate through a dictionary while its changing during for loop.您不能在 for 循环期间更改字典时迭代字典。 Make a casting to list and iterate over that list, it works for me.制作一个列表并迭代该列表,它对我有用。

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

Python 3 does not allow deletion while iterating (using for loop above) dictionary. Python 3 不允许在迭代(使用上面的 for 循环)字典时删除。 There are various alternatives to do;有多种选择; one simple way is the to change following line一种简单的方法是更改​​以下行

for i in x.keys():

With

for i in list(x)

The reason for the runtime error is that you cannot iterate through a data structure while its structure is changing during iteration.运行时错误的原因是,当数据结构在迭代过程中发生变化时,您无法迭代数据结构。

One way to achieve what you are looking for is to use list to append the keys you want to remove and then use pop function on dictionary to remove the identified key while iterating through the list.实现您正在寻找的一种方法是使用 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 situations like this, i like to make a deep copy and loop through that copy while modifying the original dict.对于这样的情况,我喜欢在修改原始字典时制作一个深层副本并循环遍历该副本。

If the lookup field is within a list, you can enumerate in the for loop of the list and then specify the position as index to access the field in the original dict.如果查找字段在列表中,则可以在列表的for循环中枚举,然后将位置指定为索引以访问原始dict中的字段。

If the values in the dictionary are unique too, then I used this solution如果字典中的值也是唯一的,那么我使用了这个解决方案

        keyToBeDeleted=None
        for k,v in mydict.items():
            if(v==match):
                keyToBeDeleted=k
                break
        mydict.pop(keyToBeDeleted,None)
  • The Python "RuntimeError: dictionary changed size during iteration" occurs when we change the size of a dictionary when iterating over it. Python “RuntimeError: dictionary changed size during iteration”发生在我们在迭代时改变字典的大小时。

  • To solve the error, use the copy() method to create a shallow copy of the dictionary that you can iterate over, eg my_dict.copy() .要解决该错误,请使用 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}
  • You can also convert the keys of the dictionary to a list and iterate over the list of keys.您还可以将字典的键转换为列表并遍历键列表。
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}

Nested null values嵌套 null 个值

Let's say we have a dictionary with nested keys, some of which are null values:假设我们有一个带有嵌套键的字典,其中一些是 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"
}

Then we can remove the null values using this function:然后我们可以使用这个 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 for pop_nested_nulls(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.

相关问题 如何解决这个python错误? RuntimeError:字典在迭代期间改变了大小 - How to fix this python error? RuntimeError: dictionary changed size during iteration 如何避免“RuntimeError: dictionary changed size during iteration”或者在没有.pop()的情况下得到结果 - How to avoid "RuntimeError: dictionary changed size during iteration" or get result without .pop() RuntimeError:词典在迭代过程中更改了大小 - RuntimeError: dictionary changed size during iteration RuntimeError:字典在迭代期间使用 defaultdict() 改变了大小 - RuntimeError : dictionary changed size during iteration with defaultdict() Python,RuntimeError:字典在迭代过程中更改了大小 - Python, RuntimeError: dictionary changed size during iteration RuntimeError:字典在python迭代期间更改了大小 - RuntimeError: dictionary changed size during iteration in python python RuntimeError:字典在迭代期间改变了大小 - python RuntimeError: dictionary changed size during iteration RuntimeError:字典在迭代过程中更改了大小-如何解决? - RuntimeError: dictionary changed size during iteration - how to solve? RuntimeError:迭代期间字典改变了大小 - 在defaultdict上使用iteritems进行迭代 - RuntimeError: dictionary changed size during iteration - During Iteration with iteritems on a defaultdict “RuntimeError:字典在迭代期间改变了大小”但它在循环中没有改变 - "RuntimeError: dictionary changed size during iteration" but it's not changed in the loop
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM