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

2025-01-09 08:47:00
admin
原创
90
摘要:问题描述:我可以在迭代 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大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用