从字典中删除元素

2025-01-17 09:22:00
admin
原创
17
摘要:问题描述:如何从 Python 中的字典中删除一个项目?在不修改原始词典的情况下,如何获得另一本删除了该项目的词典?另请参阅如何从 Python 字典中删除键?以了解删除可能尚不存在的项目(按键)的具体问题。解决方案 1:该del语句删除一个元素:del d[key] 请注意,这会改变现有字典,因此对于引用同...

问题描述:

如何从 Python 中的字典中删除一个项目?

在不修改原始词典的情况下,如何获得另一本删除了该项目的词典?


另请参阅如何从 Python 字典中删除键?以了解删除可能尚不存在的项目(按键)的具体问题。


解决方案 1:

del语句删除一个元素:

del d[key]

请注意,这会改变现有字典,因此对于引用同一实例的其他任何人来说,字典的内容都会发生变化。要返回字典,请复制该字典:

def removekey(d, key):
    r = dict(d)
    del r[key]
    return r

构造函数dict()进行浅拷贝。若要进行深拷贝,请参阅copy模块。


请注意,为每个字典/作业/等制作副本del意味着您将从恒定时间变为线性时间,并且还使用线性空间。对于小型字典,这不是问题。但是,如果您打算制作大量大型字典的副本,您可能需要不同的数据结构,例如 HAMT(如本答案中所述)。

解决方案 2:

pop改变字典。

 >>> lol = {"hello": "gdbye"}
 >>> lol.pop("hello")
     'gdbye'
 >>> lol
     {}

如果您想保留原件,只需复制它即可。

解决方案 3:

我认为您的解决方案是最好的方法。但如果您想要另一种解决方案,您可以使用旧字典中的键创建一个新字典,而不包含您指定的键,如下所示:

>>> a
{0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> {i:a[i] for i in a if i!=0}
{1: 'one', 2: 'two', 3: 'three'}

解决方案 4:

有很多很好的答案,但我想强调一点。

您可以使用dict.pop()方法和更通用的del语句从字典中删除项目。它们都会改变原始字典,因此您需要复制一份(请参阅下面的详细信息)。

KeyError如果您提供给他们的键不在字典中,他们都会引发:

key_to_remove = "c"
d = {"a": 1, "b": 2}
del d[key_to_remove]  # Raises `KeyError: 'c'`

key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove)  # Raises `KeyError: 'c'`

你必须注意以下几点:

通过捕获异常:

key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
    del d[key_to_remove]
except KeyError as ex:
    print("No such key: '%s'" % ex.message)

key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
    d.pop(key_to_remove)
except KeyError as ex:
    print("No such key: '%s'" % ex.message)

通过执行检查:

key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
    del d[key_to_remove]

key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
    d.pop(key_to_remove)

pop()还有一种更简洁的方法——提供默认返回值:

key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove, None)  # No `KeyError` here

除非您使用pop()获取要删除的键的值,否则您可以提供任何内容,而不必提供。尽管使用with checkNone可能会稍微快一些,因为它是一个具有自身复杂性的函数,会导致开销。通常情况并非如此,因此使用默认值就足够了。del`inpop()pop()`


至于主要问题,您必须复制一份您的字典,以保存原始字典并获取一份新字典,而无需删除密钥。

这里还有一些人建议使用 进行完整(深)复制copy.deepcopy(),这可能有点矫枉过正,使用copy.copy()或进行“正常”(浅)复制dict.copy()可能就足够了。字典将对对象的引用保留为键的值。因此,当您从字典中删除键时,将删除此引用,而不是引用的对象。如果内存中没有其他对对象的引用,则垃圾收集器稍后可能会自动删除对象本身。与浅复制相比,进行深复制需要进行更多计算,因此它会通过进行复制来降低代码性能,浪费内存并为 GC 提供更多工作,有时浅复制就足够了。

但是,如果您有可变对象作为字典值,并计划稍后在没有键的情况下在返回的字典中修改它们,则必须进行深度复制。

使用浅拷贝:

def get_dict_wo_key(dictionary, key):
    """Returns a **shallow** copy of the dictionary without a key."""
    _dict = dictionary.copy()
    _dict.pop(key, None)
    return _dict


d = {"a": [1, 2, 3], "b": 2, "c": 3}
key_to_remove = "c"

new_d = get_dict_wo_key(d, key_to_remove)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3], "b": 2}
new_d["a"].append(100)
print(d)  # {"a": [1, 2, 3, 100], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2}
new_d["b"] = 2222
print(d)  # {"a": [1, 2, 3, 100], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2222}

深层复制:

from copy import deepcopy


def get_dict_wo_key(dictionary, key):
    """Returns a **deep** copy of the dictionary without a key."""
    _dict = deepcopy(dictionary)
    _dict.pop(key, None)
    return _dict


d = {"a": [1, 2, 3], "b": 2, "c": 3}
key_to_remove = "c"

new_d = get_dict_wo_key(d, key_to_remove)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3], "b": 2}
new_d["a"].append(100)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2}
new_d["b"] = 2222
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2222}

解决方案 5:

del 语句就是您要找的。如果您有一个名为 foo 的字典,其中有一个名为“bar”的键,则可以像这样从 foo 中删除“bar”:

del foo['bar']

请注意,这将永久修改正在操作的字典。如果要保留原始字典,则必须事先创建一个副本:

>>> foo = {'bar': 'baz'}
>>> fu = dict(foo)
>>> del foo['bar']
>>> print foo
{}
>>> print fu
{'bar': 'baz'}

dict调用会进行浅拷贝。如果您需要深拷贝,请使用copy.deepcopy

为方便起见,您可以复制并粘贴以下方法:

def minus_key(key, dictionary):
    shallow_copy = dict(dictionary)
    del shallow_copy[key]
    return shallow_copy

解决方案 6:

...如何从字典中删除一个项目以返回一份副本(即不修改原始内容)?

dict对于此而言,使用A 的数据结构是错误的。

当然,复制字典并从副本中弹出是可行的,使用推导式构建新字典也是可行的,但所有这些复制都需要时间——您用线性时间操作取代了常量时间操作。而且,所有这些同时存在的副本都需要空间——每个副本占用线性空间。

其他数据结构,例如哈希数组映射字典树,就是为这种用例设计的:添加或删除一个元素会在对数时间内返回一个副本,并与原始元素共享其大部分存储空间。1

当然也有一些缺点。性能是对数而不是常数(尽管基数很大,通常为 32-128)。而且,虽然你可以使非变异 API 与 相同dict,但“变异”API 显然不同。最重要的是,Python 中没有 HAMT 电池。2

pyrsistent库是 HAMT 的 Python 字典替换(以及各种其他类型)的可靠实现。它甚至有一个漂亮的evolver API,可以尽可能顺利地将现有的变异代码移植到持久代码中。但如果你想明确返回副本而不是变异,你只需像这样使用它:

>>> from pyrsistent import m
>>> d1 = m(a=1, b=2)
>>> d2 = d1.set('c', 3)
>>> d3 = d1.remove('a')
>>> d1
pmap({'a': 1, 'b': 2})
>>> d2
pmap({'c': 3, 'a': 1, 'b': 2})
>>> d3
pmap({'b': 2})

d3 = d1.remove('a')正是问题所要问的。

如果您在 中嵌入了像dict和 这样的可变数据结构,那么您仍然会遇到别名问题 - 您只能通过一直向下变为不可变,嵌入s 和s 来解决该问题。list`pmappmappvector`


  1. HAMT 在 Scala、Clojure、Haskell 等语言中也变得流行,因为它们与无锁编程和软件事务内存配合得很好,但这两者与 Python 都不太相关。

  2. 事实上,stdlib 中contextvars一个 HAMT,用于 的实现。早先撤回的 PEP 解释了原因。但这是库的一个隐藏的实现细节,而不是公共集合类型。

解决方案 7:

使用 del 可以删除一个字典值,并传递该值的键

链接:
del 方法

del dictionary['key_to_del']

解决方案 8:

d = {1: 2, '2': 3, 5: 7}
del d[5]
print 'd = ', d

结果:d = {1: 2, '2': 3}

解决方案 9:

只需拨打del d['key']

然而,在生产中,检查 d 中是否存在“key”始终是一个好的做法。

if 'key' in d:
    del d['key']

解决方案 10:

不,没有别的办法了

def dictMinus(dct, val):
   copy = dct.copy()
   del copy[val]
   return copy

但是,经常创建只做了轻微改动的字典副本可能不是一个好主意,因为这会导致相对较大的内存需求。通常最好先记录旧字典(如果有必要的话),然后再进行修改。

解决方案 11:

# mutate/remove with a default
ret_val = body.pop('key', 5)
# no mutation with a default
ret_val = body.get('key', 5)

解决方案 12:

以下是顶层设计方法:

def eraseElement(d,k):
    if isinstance(d, dict):
        if k in d:
            d.pop(k)
            print(d)
        else:
            print("Cannot find matching key")
    else:
        print("Not able to delete")


exp = {'A':34, 'B':55, 'C':87}
eraseElement(exp, 'C')

我将字典和我想要的键传递给我的函数,验证它是否是字典以及键是否正确,如果两者都存在,则从字典中删除值并打印出剩余部分。

输出:{'B': 55, 'A': 34}

希望有帮助!

解决方案 13:

解决方案 1:删除

info = {'country': 'Iran'}
country = info.pop('country') if 'country' in info else None

解决方案 2:不删除

info = {'country': 'Iran'}
country = info.get('country') or None

解决方案 14:

>>> def delete_key(dict, key):
...     del dict[key]
...     return dict
... 
>>> test_dict = {'one': 1, 'two' : 2}
>>> print delete_key(test_dict, 'two')
{'one': 1}
>>>

这不会进行任何错误处理,它假定键在字典中,你可能需要先检查一下,raise如果不是

解决方案 15:

下面的代码片段肯定会对您有所帮助,我在每一行都添加了注释,这将有助于您理解代码。

def execute():
   dic = {'a':1,'b':2}
   dic2 = remove_key_from_dict(dic, 'b')  
   print(dict2)           # {'a': 1}
   print(dict)            # {'a':1,'b':2}

def remove_key_from_dict(dictionary_to_use, key_to_delete):
   copy_of_dict = dict(dictionary_to_use)     # creating clone/copy of the dictionary
   if key_to_delete in copy_of_dict :         # checking given key is present in the dictionary
       del copy_of_dict [key_to_delete]       # deleting the key from the dictionary 
   return copy_of_dict                        # returning the final dictionary

或者你也可以使用 dict.pop()

d = {"a": 1, "b": 2}

res = d.pop("c")  # No `KeyError` here
print (res)       # this line will not execute

或者更好的方法是

res = d.pop("c", "key not found")
print (res)   # key not found
print (d)     # {"a": 1, "b": 2}

res = d.pop("b", "key not found")
print (res)   # 2
print (d)     # {"a": 1}

解决方案 16:

以下是使用列表推导的另一种变体:

original_d = {'a': None, 'b': 'Some'}
d = dict((k,v) for k, v in original_d.iteritems() if v)
# result should be {'b': 'Some'}

该方法基于此帖子的答案:
从字典中删除带有空字符串的键的有效方法

对于 Python 3,这是

original_d = {'a': None, 'b': 'Some'}
d = dict((k,v) for k, v in original_d.items() if v)
print(d)

解决方案 17:

TL;DR:使用del dct[key_to_remove]dct.pop(key_to_remove)删除键。


本页给出了从字典中删除键的三个主要答案dct

  1. d = dct.copy(); del d[key_to_remove]

  2. d = dct.copy(); d.pop(key_to_remove)

  3. d = {k:v for k,v in dct.items() if k != key_to_remove}

虽然第三个选项非常容易阅读,但它不仅非常慢(因为它使用 Python 循环,而循环copy()是用 C 实现的)1,而且如以下内存跟踪所示,它的峰值内存使用量也比其他两个选项高出约 50%。此测试使用具有 10,000 个键的字典,但对于非常大的字典也存在同样的差异。在 Windows 10 AMD64 计算机上的 Python 3.12.0 上进行了测试。

import tracemalloc

def pop_key(dct, key):
    d = dct.copy()
    d.pop(key)
    return d

def del_key(dct, key):
    d = dct.copy()
    del d[key]
    return d

def dict_comp(dct, key):
    return {k: v for k,v in dct.items() if k!=key}


if __name__ == '__main__':
    dct = {str(i): i for i in range(10000)}
    key = "1"
    for func in (dict_comp, pop_key, del_key):
        tracemalloc.start()
        x = func(dct, key)
        size, peak = tracemalloc.get_traced_memory()
        tracemalloc.stop()
        print(f"{func.__name__:<9}: peak = {peak/1024:.3f} KB.")


dict_comp: peak = 304.117 KB.
pop_key  : peak = 202.688 KB.
del_key  : peak = 202.688 KB.

1如以下 timeit 测试所示,选项 3 比其他两个选项慢 10 倍左右。以下测试使用包含 10k 个键的字典,但您可以验证这种差异对于更大的字典也适用。

if __name__ == '__main__':
    dct = {str(i): i for i in range(10000)}
    key = "1"
    for func in (dict_comp, pop_key, del_key):
        tm = min(timeit.repeat(lambda: func(dct, key), number=100))/100
        print(f"{func.__name__:<9}: {tm:.6f} s")


dict_comp: 0.001415 s
pop_key  : 0.000142 s
del_key  : 0.000142 s

解决方案 18:

    species = {'HI': {'1': (1215.671, 0.41600000000000004),
  '10': (919.351, 0.0012),
  '1025': (1025.722, 0.0791),
  '11': (918.129, 0.0009199999999999999),
  '12': (917.181, 0.000723),
  '1215': (1215.671, 0.41600000000000004),
  '13': (916.429, 0.0005769999999999999),
  '14': (915.824, 0.000468),
  '15': (915.329, 0.00038500000000000003),
 'CII': {'1036': (1036.3367, 0.11900000000000001), '1334': (1334.532, 0.129)}}

以下代码将复制 dictspecies并删除不在trans_HI

trans_HI=['1025','1215']
for transition in species['HI'].copy().keys():
    if transition not in trans_HI:
        species['HI'].pop(transition)

解决方案 19:

在 Python 3 中,“dict”对象没有属性“remove”。

但是使用immutables包,可以执行允许将更改应用于 Map 对象并创建新的(派生的)Maps 的突变:

import immutables
map = immutables.Map(a=1, b=2)
map1 = map.delete('b')
print(map, map1)
# will print:
#   <immutables.Map({'b': 2, 'a': 1})>
#   <immutables.Map({'a': 1})>

解决方案 20:

您可以尝试我的方法。一行即可。

yourList = [{'key':'key1','version':'1'},{'key':'key2','version':'2'},{'key':'key3','version':'3'}]
resultList = [{'key':dic['key']} for dic in yourList if 'key' in dic]
print(resultList)
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1048  
  在产品开发领域,如何提升产品交付质量一直是企业关注的焦点。集成产品开发(IPD)作为一种系统化的产品开发方法,通过跨职能团队的协同、流程的优化以及资源的整合,能够有效提升产品的交付质量。IPD培训作为推动这一方法落地的重要工具,不仅能够帮助团队理解IPD的核心原则,还能通过实践和案例学习,提升团队的执行力和协作效率。本...
IPD研发管理体系   0  
  在现代企业中,跨部门合作已成为项目成功的关键因素之一。随着业务复杂性的增加,单一部门难以独立完成复杂的项目任务,因此需要多个部门的协同努力。然而,跨部门合作往往面临沟通不畅、职责不清、资源冲突等挑战,这些问题如果得不到有效解决,将直接影响项目的进度和质量。在这种背景下,IPD(集成产品开发)项目流程图作为一种系统化的管...
华为IPD流程   0  
  在研发IPD(集成产品开发)流程中,跨部门协作是确保项目成功的关键因素之一。IPD流程强调从概念到市场的全生命周期管理,涉及市场、研发、制造、供应链等多个部门的协同工作。然而,由于各部门的目标、工作方式和优先级不同,跨部门协作往往面临沟通不畅、资源冲突、决策延迟等挑战。为了应对这些挑战,企业需要采取系统化的方法,优化跨...
IPD概念阶段   0  
  在项目管理的生命周期中,CDCP(Concept Development and Control Plan)阶段是项目从概念到实施的关键过渡期。这一阶段不仅需要明确项目的目标和范围,还需要确保项目团队能够灵活应对可能出现的变更和调整。变更管理在这一阶段尤为重要,因为任何未经控制的变更都可能对项目的进度、成本和质量产生深...
IPD流程中TR   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用