样品:
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。
有没有更好的方法来实现这一目标?
答案 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__
上的in
(dict
)是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")
等等。或者您想要的任何值。