从字典中删除元素

时间:2011-04-30 21:20:58

标签: python dictionary pop del

有没有办法从Python中删除字典中的项目?

此外,如何从字典中删除项目以返回副本(即不修改原件)?

16 个答案:

答案 0 :(得分:1459)

del statement删除了一个元素:

del d[key]

但是,这会改变现有字典,因此字典的内容会针对具有对同一实例的引用的任何其他人进行更改。要返回 new 字典,请复制字典:

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

dict()构造函数生成浅层副本。要制作深层副本,请参阅copy module


请注意为每个字典del /赋值/等制作副本。意味着你从恒定时间到线性时间,也使用线性空间。对于小的dicts,这不是问题。但是如果你打算制作大量dicts的大量副本,你可能想要一个不同的数据结构,比如HAMT(如this answer中所述)。

答案 1 :(得分:194)

pop改变字典。

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

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

答案 2 :(得分:66)

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

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

答案 3 :(得分:51)

del statement正是您所寻找的。如果你有一个名为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

答案 4 :(得分:41)

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

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

如果你提供给他们的密钥不在字典中,他们都会提出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()具有默认值就足够了。

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

其他一些人建议使用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 :(得分:17)

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

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

答案 6 :(得分:13)

只需致电del d ['key']。

但是,在制作中,检查d中是否存在“键”始终是一个好习惯。

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

答案 7 :(得分:13)

  

...如何从字典中删除项目以返回副本(即不修改原文)?

dict是用于此目的的错误数据结构。

当然,复制dict并从复制中弹出也是如此,构建一个具有理解力的新dict也是如此,但所有复制都需要时间 - 你已经用线性时间替换了一个恒定时间操作。所有这些副本一次存活,每个副本占用空间线性空间。

其他数据结构(如hash array mapped tries)专为此类用例而设计:添加或删除元素会在对数时间内返回副本,并将其大部分存储空间与原始 1

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

pyrsistent库是基于HAMT的dict替换(以及其他各种类型)的非常可靠的实现。它甚至有一个漂亮的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中嵌入了listpmap这样的可变数据结构,那么您仍然会遇到别名问题 - 您只能通过将所有内容置于不可变状态来解决这个问题。向下,嵌入pmappvector s。

<子> 1。 HAMT在Scala,Clojure,Haskell等语言中也很受欢迎,因为它们在无锁编程和软件事务内存方面表现非常出色,但这些都与Python无关。

<子> 2。实际上, stdlib中的HAMT,用于contextvars的实现。 The earlier withdrawn PEP explains why.但这是库的隐藏实现细节,而不是公共集合类型。

答案 8 :(得分:7)

不,除了

之外别无他法
def dictMinus(dct, val):
   copy = dct.copy()
   del copy[val]
   return copy

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

答案 9 :(得分:5)

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

这不执行任何错误处理,它假设密钥在dict中,您可能想要先检查它,如果不是<{p}}则需要{/ 1}

答案 10 :(得分:5)

这是一种顶级设计方法:

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

我将字典和我想要的密钥传递给我的函数,验证它是否是字典,如果密钥是否正常,如果两者都存在,则从字典中删除值并打印出剩余的字符。< / p>

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

希望有所帮助!

答案 11 :(得分:4)

Lowest

答案 12 :(得分:3)

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

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}

答案 13 :(得分:2)

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

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

该方法基于这篇文章的答案: Efficient way to remove keys with empty strings from a dict

答案 14 :(得分:0)

    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)

答案 15 :(得分:-1)

可以试试我的方法。一行。

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)