从字典中删除一个元素

如何在Python中从字典中删除项目?

在不修改原始字典的情况下,如何在删除项的情况下获得另一个字典?

2492659 次浏览

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

del foo['bar']

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

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

#0调用进行浅拷贝。如果您想要深拷贝,请使用#1

这是一个你可以复制和粘贴的方法,为了你的方便:

def minus_key(key, dictionary):shallow_copy = dict(dictionary)del shallow_copy[key]return shallow_copy
d = {1: 2, '2': 3, 5: 7}del d[5]print 'd = ', d

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

#0语句删除了一个元素:

del d[key]

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

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

dict()构造函数创建浅拷贝。要创建深度副本,请参阅#1模块


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

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

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

>>> 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'}

不,没有别的办法

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

然而,经常创建只稍微修改过的字典的副本可能不是一个好主意,因为它会导致相对较大的内存需求。通常最好记录旧字典(如果有必要),然后修改它。

这是使用列表理解的另一个变体:

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)

#0修改字典。

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

如果你想保留原件,你可以复制它。

简单地调用del d['key']。

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

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

这里有一个顶级设计方法:

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}

希望有帮助!

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

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

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

它们都将引发一个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()来获取要删除的键的值,否则您可以提供任何东西,而不是必要的None。虽然可能使用delin检查更快,因为pop()是一个函数,有自己的并发症导致开销。通常情况并非如此,所以pop()带有默认值就足够了。


至于主要问题,您必须复制您的字典,以保存原始字典并在不删除密钥的情况下获得新字典。

这里还有一些人建议用#0做一个完整的(深度)拷贝,这可能有点矫枉过正,一个“普通的”(浅层)拷贝,用#1#2可能就足够了。字典会保留一个对对象的引用作为键的值。所以当你从字典中删除一个键时,这个引用会被删除,而不是被引用的对象。如果内存中没有其他引用,对象本身稍后可能会被垃圾收集器自动删除。与浅层拷贝相比,制作深度拷贝需要更多的计算,所以它会通过制作拷贝来降低代码性能,浪费内存并为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"] = 2222print(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"] = 2222print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}print(new_d)  # {"a": [1, 2, 3, 100], "b": 2222}

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

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 dictionaryif key_to_delete in copy_of_dict :         # checking given key is present in the dictionarydel copy_of_dict [key_to_delete]       # deleting the key from the dictionaryreturn copy_of_dict                        # returning the final dictionary

也可以使用dict.pop()

d = {"a": 1, "b": 2}
res = d.pop("c")  # No `KeyError` hereprint (res)       # this line will not execute

或者更好的方法是

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

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

dict是错误的数据结构。

当然,复制字典并从副本中弹出是有效的,构建一个具有理解能力的新字典也是如此,但所有这些复制都需要时间——你已经用线性时间操作取代了恒定时间操作。所有这些同时存在的副本都占用空间——每个副本的线性空间。

其他数据结构,如哈希数组映射尝试,正是为这种用例而设计的:添加或删除元素返回副本在对数时间内,与原始存储共享大部分存储空间1

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

#0库是Python基于HAMT的字典替换(以及各种其他类型)的非常可靠的实现。它甚至有一个漂亮的开发API,用于将现有突变代码尽可能平滑地移植到持久代码。但是如果你想明确地返回副本而不是突变,你只需这样使用它:

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

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

如果你在pmap中嵌入了像dictlist这样的可变数据结构,你仍然会有混淆现象——你只能通过一直不可变来解决这个问题,嵌入pmappvector


1. HAMT在Scala、Clojure、Haskell等语言中也很受欢迎,因为它们可以很好地处理无锁编程和软件事务内存,但这两者在Python中都不太相关。

2.事实上,stdlib中有一个HAMT,用于实现contextvars前面撤回的PEP解释了原因。

    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)}}

下面的代码将复制一个字典species并删除不在trans_HI中的项目

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

可以试试我的方法。在一条线上。

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)

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

链接:del方法

del dictionary['key_to_del']

解决方案1:删除

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

解决方案2:不删除

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