从字典中删除元素的方法

从字典中删除元素的方法

技术背景

在Python编程中,字典(dict)是一种常用的数据结构,用于存储键值对。在实际开发中,经常会遇到需要从字典中删除特定元素的场景。然而,不同的删除方式可能会对原字典产生不同的影响,同时在性能和内存使用上也存在差异。

实现步骤

直接删除元素(修改原字典)

可以使用del语句或pop方法直接从字典中删除元素,这两种方法都会修改原字典。

1
2
3
4
5
6
7
8
9
10
11
12
# 使用del语句
d = {"a": 1, "b": 2}
key_to_remove = "a"
del d[key_to_remove]
print(d) # 输出: {'b': 2}

# 使用pop方法
d = {"a": 1, "b": 2}
key_to_remove = "a"
value = d.pop(key_to_remove)
print(d) # 输出: {'b': 2}
print(value) # 输出: 1

删除元素并返回新字典(不修改原字典)

如果需要保留原字典,可以先复制一份字典,再进行删除操作。可以使用浅复制或深复制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 浅复制
def get_dict_wo_key_shallow(dictionary, 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_shallow(d, key_to_remove)
print(d) # 输出: {'a': [1, 2, 3], 'b': 2, 'c': 3}
print(new_d) # 输出: {'a': [1, 2, 3], 'b': 2}

# 深复制
from copy import deepcopy

def get_dict_wo_key_deep(dictionary, 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_deep(d, key_to_remove)
print(d) # 输出: {'a': [1, 2, 3], 'b': 2, 'c': 3}
print(new_d) # 输出: {'a': [1, 2, 3], 'b': 2}

使用字典推导式创建新字典

通过字典推导式可以创建一个不包含指定键的新字典。

1
2
3
a = {0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
new_a = {i: a[i] for i in a if i != 0}
print(new_a) # 输出: {1: 'one', 2: 'two', 3: 'three'}

核心代码

以下是一个封装好的函数,用于删除字典中的指定键并返回新字典:

1
2
3
4
5
6
7
8
9
10
def remove_key(d, key):
r = dict(d)
del r[key]
return r

d = {"a": 1, "b": 2, "c": 3}
key_to_remove = "b"
new_d = remove_key(d, key_to_remove)
print(d) # 输出: {'a': 1, 'b': 2, 'c': 3}
print(new_d) # 输出: {'a': 1, 'c': 3}

最佳实践

处理键不存在的情况

使用del语句或pop方法时,如果键不存在,会引发KeyError。可以通过捕获异常或进行键检查来避免这种情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 捕获异常
key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
del d[key_to_remove]
except KeyError as ex:
print(f"No such key: '{ex}'")

# 进行键检查
key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
del d[key_to_remove]

# 使用pop方法提供默认值
key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove, None) # 不会引发KeyError

性能考虑

在处理大量数据时,使用del语句或pop方法结合浅复制的方式性能较好,而字典推导式的性能相对较差。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import tracemalloc
import timeit

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.")

# 时间测试
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")

常见问题

KeyError异常

当使用del语句或pop方法删除不存在的键时,会引发KeyError。可以通过捕获异常或进行键检查来避免。

浅复制和深复制的选择

如果字典的值是不可变对象,浅复制通常就足够了;如果值是可变对象,并且后续需要对新字典中的值进行修改,建议使用深复制。

性能问题

在处理大量数据时,频繁复制字典会导致性能下降和内存使用增加。可以考虑使用其他数据结构,如哈希数组映射树(HAMT),pyrsistent库提供了基于HAMT的字典替代方案。

1
2
3
4
5
6
from pyrsistent import m

d1 = m(a=1, b=2)
d3 = d1.remove('a')
print(d1) # 输出: pmap({'a': 1, 'b': 2})
print(d3) # 输出: pmap({'b': 2})

从字典中删除元素的方法
https://119291.xyz/posts/delete-an-element-from-a-dictionary/
作者
ww
发布于
2025年5月19日
许可协议