繁体   English   中英

如何解决迭代错误期间字典更改大小?

[英]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)  

这是解决它的一种方法:

  1. 从字典中获取键列表,按值排序
  2. 由于此列表中的第一个键具有最小值,因此您可以对它进行任何操作。

这是一个示例:

# 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM