从字典中删除一个元素
How do I delete an item from a dictionary in Python?
Without modifying the original dictionary, how do I obtain another dict with the item removed?
See also How can I remove a key from a Python dictionary? for the specific issue of removing an item (by key) that may not already be present.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(20)
TL;DR: 使用
del dct[key_to_remove]
或dct.pop(key_to_remove)
删除键。本页给出了从字典 dct 中删除键的三个主要答案:
d = dct.copy(); d.pop(key_to_remove)
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 上进行了测试。1 正如下面的 timeit 测试所示,选项 3 比其他两个慢大约 10 倍。以下测试使用具有 10k 个键的字典,但您可以验证差异是否也适用于更大的字典。
TL;DR: Use either
del dct[key_to_remove]
ordct.pop(key_to_remove)
to remove keys.There are three main answers given on this page to remove a key from a dictionary
dct
:d = dct.copy(); del d[key_to_remove]
d = dct.copy(); d.pop(key_to_remove)
d = {k:v for k,v in dct.items() if k != key_to_remove}
While the third option is very easy to read, it is not only very slow (because it uses a Python loop while
copy()
is implemented in C)1, as the following memory tracing shows, it also has about 50% more peak memory usage than the other two options. This test uses a dictionary with 10,000 keys but the same difference holds for extremely large dictionaries as well. Tested on Python 3.12.0 on a Windows 10 AMD64 machine.1 As the following timeit test shows, option 3 is about 10 times slower than the other two. The following test uses a dictionary with 10k keys but you can verify that the difference holds for much larger dictionaries as well.
以下代码将复制字典
species
并删除trans_HI
中不存在的项目The following code will make a copy of dict
species
and delete items which are not intrans_HI
在Python 3中,“dict”对象没有属性“remove”。
但是使用 immutables 包,可以执行突变,允许将更改应用于 Map 对象并创建新的(派生的) ) 地图:
In Python 3, 'dict' object has no attribute 'remove'.
But with immutables package, can perform mutations that allow to apply changes to the Map object and create new (derived) Maps:
可以试试我的方法。在一行中。
can try my method. In one line.
del
语句 删除一个元素:请注意,这会改变现有的字典,因此对于引用同一实例的其他任何人来说,字典的内容都会发生变化。要返回新字典,请创建字典的副本:
dict()
构造函数创建浅表副本。要进行深层复制,请参阅copy
模块。请注意,为每个字典
del
/assignment/etc 制作一个副本。意味着您将从恒定时间变为线性时间,并且还使用线性空间。对于小字典来说,这不是问题。但是,如果您计划制作大量大型字典的副本,您可能需要不同的数据结构,例如 HAMT(如 中所述)这个答案)。The
del
statement removes an element:Note that this mutates the existing dictionary, so the contents of the dictionary changes for anybody else who has a reference to the same instance. To return a new dictionary, make a copy of the dictionary:
The
dict()
constructor makes a shallow copy. To make a deep copy, see thecopy
module.Note that making a copy for every dict
del
/assignment/etc. means you're going from constant time to linear time, and also using linear space. For small dicts, this is not a problem. But if you're planning to make lots of copies of large dicts, you probably want a different data structure, like a HAMT (as described in this answer).pop
改变字典。如果您想保留原件,只需复制即可。
pop
mutates the dictionary.If you want to keep the original you could just copy it.
我认为你的解决方案是最好的方法。但是如果您想要另一个解决方案,您可以使用旧字典中的键创建一个新字典,而不包含指定的键,如下所示:
I think your solution is best way to do it. But if you want another solution, you can create a new dictionary with using the keys from old dictionary without including your specified key, like this:
有很多很好的答案,但我想强调一件事。
您可以同时使用
dict.pop()
< /a> 方法和更通用的del
语句 从字典中删除项目。它们都会改变原始字典,因此您需要复制一份(请参阅下面的详细信息)。它们都会引发
KeyError
< /a> 如果您提供给他们的密钥不在字典中:并且
您必须处理此问题:
通过捕获异常:
和
通过执行支票:
和
但是
pop()
还有一种更简洁的方法 - 提供默认返回值:除非您使用
pop()
来获取要删除的键的值您可以提供任何内容,非必要的无
。尽管使用
del
和in
检查可能会稍微更快,因为pop()
是一个函数它本身的复杂性导致了开销。通常情况并非如此,因此使用默认值的pop()
就足够了。至于主要问题,您必须复制字典,保存原始字典并拥有一本新字典而不删除密钥。
这里的其他一些人建议使用
制作完整(深层)副本copy.deepcopy()
,这可能是一种矫枉过正,“正常”(浅)复制,使用copy.copy()
或dict.copy()
可能就足够了。字典保留对对象的引用作为键的值。因此,当您从字典中删除键时,该引用将被删除,而不是被引用的对象。如果内存中没有其他引用,则该对象本身可能会被垃圾收集器自动删除。与浅复制相比,进行深复制需要更多的计算,因此它会通过复制降低代码性能,浪费内存并为 GC 提供更多工作,有时浅复制就足够了。但是,如果您将可变对象作为字典值,并计划稍后在返回的字典中修改它们而不需要键,则必须进行深层复制。
浅拷贝:
深拷贝:
There're a lot of nice answers, but I want to emphasize one thing.
You can use both
dict.pop()
method and a more genericdel
statement to remove items from a dictionary. They both mutate the original dictionary, so you need to make a copy (see details below).And both of them will raise a
KeyError
if the key you're providing to them is not present in the dictionary:and
You have to take care of this:
by capturing the exception:
and
by performing a check:
and
but with
pop()
there's also a much more concise way - provide the default return value:Unless you use
pop()
to get the value of a key being removed you may provide anything, not necessaryNone
.Though it might be that using
del
within
check is slightly faster due topop()
being a function with its own complications causing overhead. Usually it's not the case, sopop()
with default value is good enough.As for the main question, you'll have to make a copy of your dictionary, to save the original dictionary and have a new one without the key being removed.
Some other people here suggest making a full (deep) copy with
copy.deepcopy()
, which might be an overkill, a "normal" (shallow) copy, usingcopy.copy()
ordict.copy()
, might be enough. The dictionary keeps a reference to the object as a value for a key. So when you remove a key from a dictionary this reference is removed, not the object being referenced. The object itself may be removed later automatically by the garbage collector, if there're no other references for it in the memory. Making a deep copy requires more calculations compared to shallow copy, so it decreases code performance by making the copy, wasting memory and providing more work to the GC, sometimes shallow copy is enough.However, if you have mutable objects as dictionary values and plan to modify them later in the returned dictionary without the key, you have to make a deep copy.
With shallow copy:
With deep copy:
del 语句 就是您要查找的内容。如果您有一个名为 foo 的字典,其中包含一个名为“bar”的键,则可以像这样从 foo 中删除“bar”:
请注意,这会永久修改正在操作的字典。如果您想保留原始字典,则必须事先创建一个副本:
dict
调用会进行浅复制。如果您想要深层复制,请使用copy.deepcopy
。这是一个方法,您可以复制并使用它。为了方便起见,粘贴:
The del statement is what you're looking for. If you have a dictionary named foo with a key called 'bar', you can delete 'bar' from foo like this:
Note that this permanently modifies the dictionary being operated on. If you want to keep the original dictionary, you'll have to create a copy beforehand:
The
dict
call makes a shallow copy. If you want a deep copy, usecopy.deepcopy
.Here's a method you can copy & paste, for your convenience:
dict
是用于此目的的错误数据结构。当然,复制字典并从副本中弹出是可行的,使用理解构建一个新字典也是如此,但所有复制都需要时间 - 您已经用线性时间操作替换了恒定时间操作。所有这些活着的副本同时占用空间——每个副本的线性空间。
其他数据结构,例如哈希数组映射尝试,正是针对这种用例而设计的:或者删除一个元素会在对数时间内返回一个副本,与原始元素共享大部分存储空间。1
当然,也有一些缺点。性能是对数而不是常数(尽管基数很大,通常为 32-128)。而且,虽然您可以使非变异 API 与 dict 相同,但“变异”API 显然是不同的。而且,最重要的是,Python 中不包含 HAMT 电池。2
Pyrcient
库是 Python 的基于 HAMT 的字典替换(以及各种其他类型)的非常可靠的实现。它甚至有一个漂亮的 evolver API 用于将现有的变异代码移植到持久代码尽可能顺利。但是,如果您想明确返回副本而不是变异,只需像这样使用它:d3 = d1.remove('a')
正是问题所要求的。如果您在
pmap
中嵌入了诸如dict
和list
之类的可变数据结构,您仍然会遇到别名问题 - 您只能修复通过始终保持不变,嵌入pmap
和pvector
来实现。<子>1。 HAMT 在 Scala、Clojure、Haskell 等语言中也很流行,因为它们非常适合无锁编程和软件事务内存,但这些在 Python 中都不太相关。
2.事实上,stdlib 中有一个 HAMT,用于实现
contextvars
。 之前撤回的 PEP 解释了原因。 但是这是库的隐藏实现细节,而不是公共集合类型。A
dict
is the wrong data structure to use for this.Sure, copying the dict and popping from the copy works, and so does building a new dict with a comprehension, but all that copying takes time—you've replaced a constant-time operation with a linear-time one. And all those copies alive at once take space—linear space per copy.
Other data structures, like hash array mapped tries, are designed for exactly this kind of use case: adding or removing an element returns a copy in logarithmic time, sharing most of its storage with the original.1
Of course there are some downsides. Performance is logarithmic rather than constant (although with a large base, usually 32-128). And, while you can make the non-mutating API identical to
dict
, the "mutating" API is obviously different. And, most of all, there's no HAMT batteries included with Python.2The
pyrsistent
library is a pretty solid implementation of HAMT-based dict-replacements (and various other types) for Python. It even has a nifty evolver API for porting existing mutating code to persistent code as smoothly as possible. But if you want to be explicit about returning copies rather than mutating, you just use it like this:That
d3 = d1.remove('a')
is exactly what the question is asking for.If you've got mutable data structures like
dict
andlist
embedded in thepmap
, you'll still have aliasing issues—you can only fix that by going immutable all the way down, embeddingpmap
s andpvector
s.1. HAMTs have also become popular in languages like Scala, Clojure, Haskell because they play very nicely with lock-free programming and software transactional memory, but neither of those is very relevant in Python.
2. In fact, there is an HAMT in the stdlib, used in the implementation of
contextvars
. The earlier withdrawn PEP explains why. But this is a hidden implementation detail of the library, not a public collection type.使用 del 你可以删除一个字典值,传递该值的键
链接:
del 方法
Using del you can remove a dict value passing the key of that value
Link:
del method
结果:
d = {1: 2, '2': 3}
Result:
d = {1: 2, '2': 3}
只需调用
del d['key']
。然而,在生产中,检查 d 中是否存在“key”始终是一个好习惯。
Simply call
del d['key']
.However, in production, it is always a good practice to check if 'key' exists in d.
不,没有其他办法,
但是,通常创建仅稍加更改的字典的副本可能不是一个好主意,因为这会导致相对较大的内存需求。通常最好记录旧字典(如果有必要的话)然后修改它。
No, there is no other way than
However, often creating copies of only slightly altered dictionaries is probably not a good idea because it will result in comparatively large memory demands. It is usually better to log the old dictionary(if even necessary) and then modify it.
这里是一个顶层设计方法:
我将字典和我想要的键传递到我的函数中,验证它是否是字典以及键是否正常,如果两者都存在,则从字典中删除值并打印出左侧- 结束。
输出:
{'B': 55, 'A': 34}
希望有帮助!
Here a top level design approach:
I'm passing the dictionary and the key I want into my function, validates if it's a dictionary and if the key is okay, and if both exist, removes the value from the dictionary and prints out the left-overs.
Output:
{'B': 55, 'A': 34}
Hope that helps!
解决方案 1:删除
解决方案 2:不删除
Solution 1: with deleting
Solution 2: without deleting
这不会进行任何错误处理,它假设密钥在字典中,您可能需要首先检查它,如果不是,则
raise
this doesn't do any error handling, it assumes the key is in the dict, you might want to check that first and
raise
if its not下面的代码片段肯定会对您有所帮助,我在每一行中添加了注释,这将有助于您理解代码。
或者你也可以使用 dict.pop()
或者更好的方法是
Below code snippet will help you definitely, I have added comments in each line which will help you in understanding the code.
or you can also use dict.pop()
or the better approach is
这是使用列表理解的另一种变体:
该方法基于这篇文章的答案:
从 a 中删除带有空字符串的键的有效方法dict
对于 Python 3 这是
Here's another variation using list comprehension:
The approach is based on an answer from this post:
Efficient way to remove keys with empty strings from a dict
For Python 3 this is