根据键列表将一个字典的部分复制到新字典

1 投票
4 回答
2654 浏览
提问于 2025-04-18 18:53

示例:

d = {
    "test": 1,
    "sample": 2,
    "example": 3,
    "product": 4,
    "software": 5,
    "demo": 6,
}

filter_keys = ["test","sample","example","demo"]

我想创建一个新的字典,这个字典只包含第一个字典中那些键在列表里的项目。换句话说,我想要:

d2 = {
    "test": 1,
    "sample": 2,
    "example": 3,
    "demo": 6,
}

我可以用循环来实现这个:

d2 = {}
for k in d.keys():
    if (k in filter_keys): 
        d2[k] = d[k]

但是这样做看起来有点“不够Python风格”。我还猜,如果你的字典很大,比如有5000个项目,那不断往新字典里添加新项目会比较慢,没那么高效。

另外,你还需要处理错误。如果列表里有一些不是字典键的东西,它应该被忽略。或者说,它可以被添加到新字典里,但值设为None。

有没有更好的方法来做到这一点呢?

4 个回答

0

关于你问题的最后一部分:

或者它可能会被添加到新的字典中,但值为None。

l = ["test","sample","example","demo","badkey"]
d = {
    "test": 1,
    "sample": 2,
    "example": 3,
    "product": 4,
    "software": 5,
    "demo": 6,
}


print {k: d.get(k) for k in l}
{'test': 1, 'sample': 2, 'badkey': None, 'example': 3, 'demo': 6}

你可以给dict.get设置一个默认返回值,默认情况下是None,但你也可以把它设置成d.get(k,"No_match"),或者你想要的任何值。

1

为了获得最佳性能,你应该先遍历列表中的键,然后检查这些键是否在字典里,而不是反过来这样做:

d2 = {}
for k in list_of_keys:
    if k in d:
       d2[k] = d[k]

这样做的好处是,使用字典的 dict.__contains__ (也就是 in)操作时,查找的时间复杂度是 O(1),而对于列表来说,查找的时间复杂度是 O(N)。对于很大的列表来说,这个差别非常大(O(N) 的算法和 O(N^2) 的算法相比)。

我们可以用一种更简洁的方式来表达上面的循环,使用字典推导式:

d2 = {k: d[k] for k in list_of_keys if k in d} 

这个方法可能会比循环稍微快一点,但其实差别不大,没必要太担心。不过,大多数 Python 程序员会更喜欢这种写法,因为它更简洁,而且很常见。

1

字典推导式是一种实现这个功能的方法:

new_d = {k: v for k, v in d.items() if k in l}

示例:

>>> d = {
...     "test": 1,
...     "sample": 2,
...     "example": 3,
...     "product": 4,
...     "software": 5,
...     "demo": 6,
... }
>>>
>>> l = ["test","sample","example","demo"]
>>> new_d = {k: v for k, v in d.items() if k in l}
>>> new_d
{'sample': 2, 'demo': 6, 'test': 1, 'example': 3}
5

一种简单的方法是使用“字典推导式”:

filtered_dict = {key: value for key, value in d.items() if key in filter_keys}

注意,如果条件放在推导式的最后,它会过滤掉循环语句的执行。根据字典中的键的数量是否大于你想要过滤的键的数量,这种修改可能会更有效:

filtered_dict = {key: d[key] for key in filter_keysif key in d}

在字典中检查某个键是否存在(key in d)要比在过滤键列表中检查(key in filter_keys)快很多。不过,哪个更快取决于过滤键列表的大小(还有,字典的大小影响较小)。

如果不使用字典推导式,还有一种相对“Python”的方法,就是用dict构造函数:

filtered_dict = dict([(key, value) for key, value in d.items() if key in filter_keys])

注意,这基本上和字典推导式是一样的,但如果你对字典推导式的语法不太熟悉,这种方式可能会更清晰。

撰写回答