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

时间:2014-08-28 18:29:44

标签: python dictionary

样品:

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

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

我想创建一个新的dict,它只包含第一个dict中的键,它们的键出现在列表中。换句话说,我想:

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

我可以用循环来做到这一点:

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

但这似乎非常“非Pythonic”。我也猜测,如果你有一个巨大的字典,比如5000个左右的项目,那么与更直接的方式相比,不断向新字典中添加新项目会很慢。

此外,您希望能够处理错误。如果列表中包含的内容不是dict中的键,则应该忽略它。或者它可能被添加到新的dict中,但值为None。

有没有更好的方法来实现这一目标?

4 个答案:

答案 0 :(得分:2)

直接的方法是使用"词典理解":

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)中的成员资格要快得多。但最终更快取决于过滤器键列表的大小(在较小程度上,取决于字典的大小)。

在没有字典理解的情况下,使用dict构造函数进行相对python的方式:

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

请注意,这基本上等同于字典理解,但如果您不熟悉字典理解语法,则可能更清楚。

答案 1 :(得分:1)

为获得最佳性能,您应该迭代列表中的键并检查它们是否在dict中而不是相反:

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

这里的好处是dict.__contains__上的indict)是O(1),而列表中的{(1}}是O(N)。对于大型列表,这是一个巨大的好处(O(N)算法与O(N ^ 2))。

我们可以通过用相同的字母理解表达上述循环来更简洁:

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

这可能比循环更快,但可能不足以担心。也就是说,大多数python程序员都喜欢这个版本,因为它更简洁,更常见。

答案 2 :(得分: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}

答案 3 :(得分:0)

根据你问题的最后部分:

或者它可能会被添加到新的dict中,但值为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")等等。或者您想要的任何值。