![](/img/trans.png)
[英]RuntimeError: dictionary changed size during iteration - how to solve?
[英]How to solve dictionary changed size during iteration error?
我想在字典中弹出所有大值及其键,并保持最小。 这是我的程序的一部分
for key,value in dictionary.items():
for key1, value1 in dictionary.items():
if key1!= key and value > value1:
dictionary.pop(key)
print (dictionary)
这导致
RuntimeError: dictionary changed size during iteration
我怎样才能避免这个错误?
在 Python3 中,尝试
for key in list(dict.keys()):
if condition:
matched
del dict[key]
循环 dict 以更新其密钥时,还有一件事应该小心:
代码1:
keyPrefix = ‘keyA’
for key, value in Dict.items():
newkey = ‘/’.join([keyPrefix, key])
Dict[newkey] = Dict.pop(key)
代码2:
keyPrefix = ‘keyA’
for key, value in Dict.keys():
newkey = ‘/’.join([keyPrefix, key])
Dict[newkey] = Dict.pop(key)
code1/code2 的结果是:
{‘keyA/keyA/keyB’ : ”, ‘keyA/keyA/keyA’: ”}
我解决这个意外结果的方法:
Dict = {‘/’.join([keyPrefix, key]): value for key, value in Dict.items()}
链接: https : //blog.gainskills.top/2016/07/21/loop-a-dict-to-update-key/
如果您正在寻找字典中的最小值,您可以这样做:
min(dictionary.values())
如果不能使用 min,则可以使用 sorted:
sorted(dictionary.values())[0]
附带说明一下,您遇到Runtime Error
的原因是在内循环中修改了外循环所基于的迭代器。 当您pop
外部循环尚未到达的条目并且外部迭代器到达它时,它会尝试访问已删除的元素,从而导致错误。
如果您尝试在 Python 2.7(而不是 3.x)上执行您的代码,实际上您会得到一个Key Error
。
如果要根据迭代器修改循环内的可迭代对象,则应使用它的深层副本。
您可以使用copy.deepcopy制作原始 dict 的副本,在更改原始副本的同时循环复制副本。
from copy import deepcopy
d=dict()
for i in range(5):
d[i]=str(i)
k=deepcopy(d)
d[2]="22"
print(k[2])
#The result will be 2.
你的问题是迭代你正在改变的东西。
在循环过程中记录键,然后在循环完成时执行 dictionary.pop(key) 。 像这样:
for key,value in dictionary.items():
for key1, value1 in dictionary.items():
if key1!= key and value > value1:
storedvalue = key
dictionary.pop(key)
这是解决它的一种方法:
这是一个示例:
# A list of grades, not in any order
grades = dict(John=95,Amanda=89,Jake=91,Betty=97)
# students is a list of students, sorted from lowest to highest grade
students = sorted(grades, key=lambda k: grades[k])
print 'Grades from lowest to highest:'
for student in students:
print '{0} {1}'.format(grades[student], student)
lowest_student = students[0]
highest_student = students[-1]
print 'Lowest grade of {0} belongs to {1}'.format(grades[lowest_student], lowest_student)
print 'Highest grade of {0} belongs to {1}'.format(grades[highest_student], highest_student)
这里的秘诀在于 sorted() 函数:我们不是按键排序,而是按值排序。
当我现在阅读您的循环时,您希望只保留一个最小的元素,但不使用min
。 因此,请执行与您的代码现在相反的操作,检查value1 < minValueSoFar
,如果是,则将 key1 保留为 minKeySoFar。 然后在循环结束时(如 Zayatzz 建议的那样),做一个dictionary.pop(minKeySoFar)
key1!=key
说一句,我注意到key1!=key
测试是无关紧要的,并且假设一个相当长的列表在计算上效率低下。
minValueSoFar = 9999999; # or whatever
for key,value in dictionary.items():
if value < minValueSoFar:
minValueSoFar = value
minKeySoFar = key
dictionary.pop(minKeySoFar) # or whatever else you want to do with the result
如果您只想保留具有最小值的键,我会先找到该项目,然后创建一个仅包含它的新字典。 如果你的字典是d
,这样的事情会在一行中完成:
d = dict((min(d.items(), key=lambda item: item[1]),))
这不仅可以避免在迭代时更新字典的任何问题,而且可能比删除所有其他元素更快。
如果您出于某种原因必须就地进行修改,则以下方法会起作用,因为它会在修改字典之前复制所有键:
key_to_keep = min(d.items(), key=lambda item: item[1])[0]
for key in list(d):
if key != key_to_keep:
d.pop(key)
字典在迭代期间改变大小的替代解决方案:
for key,value in list(dictionary.items()):
for key1, value1 in list(dictionary.items()):
if key1!= key and value > value1:
dictionary.pop(key)
print (dictionary)
最好谨慎使用! 当使用这种类型的代码时,因为
list(dictionary.items())
在编译器第一次进入循环时计算的。 因此,对字典所做的任何更改都不会影响当前循环内的进程。
您可以使用要删除的值创建一个列表,然后再运行一个 for 循环:
for entry in (listofkeystopop):
dictionary.pop(entry)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.