如何在迭代字典时删除其中的项目?

2025-01-09 08:47:00
admin
原创
92
摘要:问题描述:我可以在迭代 Python 字典时删除其中的项目吗?我想从字典中删除不满足特定条件的元素,而不是创建一个全新的字典。以下是一个好的解决方案吗?或者有更好的方法吗?for k, v in mydict.items(): if k == val: del mydict[k] 解决...

问题描述:

我可以在迭代 Python 字典时删除其中的项目吗?

我想从字典中删除不满足特定条件的元素,而不是创建一个全新的字典。以下是一个好的解决方案吗?或者有更好的方法吗?

for k, v in mydict.items():
    if k == val:
        del mydict[k]

解决方案 1:

对于Python 3+

>>> mydict
{'four': 4, 'three': 3, 'one': 1}

>>> for k in list(mydict.keys()):
...     if mydict[k] == 3:
...         del mydict[k]

>>> mydict
{'four': 4, 'one': 1}

其他答案对于Python 2来说很好,但RuntimeError对于Python 3来说却引发了一个问题:

RuntimeError:字典在迭代过程中改变了大小。

发生这种情况是因为mydict.keys()返回的是迭代器而不是列表。正如评论中指出的那样,只需将其转换mydict.keys()为列表list(mydict.keys())即可。


对于Python 2

控制台中的一个简单测试表明,在迭代字典时无法修改它:

>>> mydict = {'one': 1, 'two': 2, 'three': 3, 'four': 4}

>>> for k, v in mydict.iteritems():
...    if k == 'two':
...        del mydict[k]

------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython console>", line 1, in <module>
RuntimeError: dictionary changed size during iteration

正如 delnan 的回答所述,当迭代器尝试移至下一个条目时,删除条目会导致问题。相反,请使用该keys()方法获取键列表并使用该列表:

>>> for k in mydict.keys():
...    if k == 'two':
...        del mydict[k]

>>> mydict
{'four': 4, 'three': 3, 'one': 1}

如果需要根据项目值进行删除,请使用items()下列方法:

>>> for k, v in mydict.items():
...     if v == 3:
...         del mydict[k]

>>> mydict
{'four': 4, 'one': 1}

解决方案 2:

您也可以分两步进行:

remove = [k for k in mydict if k == val]
for k in remove: del mydict[k]

我最喜欢的方法通常是创建一个新的字典:

# Python 2.7 and 3.x
mydict = { k:v for k,v in mydict.items() if k!=val }
# before Python 2.7
mydict = dict((k,v) for k,v in mydict.iteritems() if k!=val)

解决方案 3:

而是对副本进行迭代,比如items()

for k, v in list(mydict.items()):

解决方案 4:

您无法在迭代集合时对其进行修改。这样会造成混乱 - 最明显的是,如果您被允许删除并删除了当前项目,迭代器将不得不继续前进 (+1),而下一次调用next将带您超越该步骤 (+2),因此您最终会跳过一个元素(即您删除的元素后面的元素)。您有两个选择:

  • 复制所有键(或值,或两者,取决于您的需要),然后迭代这些键。您可以使用.keys()et al 来实现此目的(在 Python 3 中,将生成的迭代器传递给list)。但可能会严重浪费空间。

  • 像往常一样迭代mydict,将要删除的键保存在单独的集合中to_delete。迭代完成后,从中mydict删除所有项目。与第一种方法相比,可以节省一些空间(取决于删除了多少个键以及保留了多少个键),但也需要多写几行。to_delete`mydict`

解决方案 5:

您可以使用词典理解。

d = {k:d[k] for k in d if d[k] != val}

解决方案 6:

list(mydict)可用于:

>>> mydict = {'one': 1, 'two': 2, 'three': 3, 'four': 4}
>>> for k in list(mydict):
...     if k == 'three':
...         del mydict[k]
... 
>>> mydict
{'four': 4, 'two': 2, 'one': 1}

这对应于列表的并行结构:

>>> mylist = ['one', 'two', 'three', 'four']
>>> for k in list(mylist):                            # or mylist[:]
...     if k == 'three':
...         mylist.remove(k)
... 
>>> mylist
['one', 'two', 'four']

两者均可在 python2 和 python3 中运行。

解决方案 7:

使用 python3,迭代 dic.keys() 将引发字典大小错误。您可以使用以下替代方法:

使用 python3 进行测试,它运行良好,并且没有引发错误“字典在迭代过程中改变了大小”:

my_dic = { 1:10, 2:20, 3:30 }
# Is important here to cast because ".keys()" method returns a dict_keys object.
key_list = list( my_dic.keys() )

# Iterate on the list:
for k in key_list:
    print(key_list)
    print(my_dic)
    del( my_dic[k] )


print( my_dic )
# {}

解决方案 8:

您可以先建立一个要删除的键列表,然后遍历该列表并删除它们。

dict = {'one' : 1, 'two' : 2, 'three' : 3, 'four' : 4}
delete = []
for k,v in dict.items():
    if v%2 == 1:
        delete.append(k)
for i in delete:
    del dict[i]

解决方案 9:

如果您要删除的项目始终位于字典迭代的“开始”处,那么有一种方法可能很合适

while mydict:
    key, value = next(iter(mydict.items()))
    if should_delete(key, value):
       del mydict[key]
    else:
       break

仅保证“开头”与某些 Python 版本/实现保持一致。例如,来自Python 3.7 中的新增功能

dict 对象的插入顺序保存特性已被宣布为 Python 语言规范的正式组成部分。

这种方式避免了许多其他答案所建议的字典复制,至少在 Python 3 中是这样。

解决方案 10:

我在 Python3 中尝试了上述解决方案,但当我将对象存储在字典中时,这个解决方案似乎是唯一对我有用的解决方案。基本上,你复制 dict() 并对其进行迭代,同时删除原始字典中的条目。

        tmpDict = realDict.copy()
        for key, value in tmpDict.items():
            if value:
                del(realDict[key])

解决方案 11:

单行:

my_dict = {k: v for k, v in my_dict.copy().items() if not k == value}

my_dict.copy()对象仅用于迭代,在字典理解范围之外不可用。这样可以避免编辑当前正在迭代的对象,正如@user395760 在其回答中建议的那样。

为了清楚起见,您可以将其分成多行:

my_dict = {
    k: v
    for k, v in my_dict.copy().items()
    if not k == value
}

解决方案 12:

另一种好用且有效的方法是使用部分函数

next((partial(d.pop, k) for k in d if k == v), partial(print, f"{v} key not found"))()
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1590  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1361  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   18  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   18  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   19  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用