簡體   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