排除指定键后返回字典的副本

75

我希望创建一个函数,该函数返回一个字典的副本,但不包括在一个列表中指定的键。

考虑以下字典:

my_dict = {
    "keyA": 1,
    "keyB": 2,
    "keyC": 3
}

调用 without_keys(my_dict, ['keyB', 'keyC']) 应返回:

{
    "keyA": 1
}

我想用一个简洁的字典推导式来完成这个任务,但是我遇到了麻烦。我的尝试如下:

def without_keys(d, keys):
    return {k: d[f] if k not in keys for f in d}

这是无效的语法。我该怎么做?

7个回答

80

你很接近了,尝试下面的代码片段:

>>> my_dict = {
...     "keyA": 1,
...     "keyB": 2,
...     "keyC": 3
... }
>>> invalid = {"keyA", "keyB"}
>>> def without_keys(d, keys):
...     return {x: d[x] for x in d if x not in keys}
>>> without_keys(my_dict, invalid)
{'keyC': 3}

基本上,在上面的情况下,if k not in keys会放在字典推导式的末尾。


1
你将无效声明为一个集合。有什么原因吗?列表是否也可以? - Prithvi Boinpally
2
是的,列表也可以(你可以试试),但通常当顺序对你不重要时,set 更受欢迎(即使在性能方面,在这个只有少量数据的简短示例中也不重要)。 - Nerxis
这比获取所有键,然后使用for循环手动跳过不需要的键更快吗? - sebko_iic

47

在你的字典推导式中,你应该遍历你的字典(不是 k,我也不确定那是什么)。例如 -

return {k:v for k,v in d.items() if k not in keys}

2
我更喜欢这个解决方案,因为它可以略微节省不调用 d[x] 索引操作的开销。 - Alejandro Piad
1
这是一个浅复制。 - Eissa N.

12

这应该适合你的需要。

def without_keys(d, keys):
    return {k: v for k, v in d.items() if k not in keys}

11
更简洁了。 显然 Python 3 允许您从 dict_keys 中“减去”一个 list。
def without_keys(d, keys):
    return {k: d[k] for k in d.keys() - keys}

5
请注意,使用keys()而不是items()会慢大约33%:https://discuss.python.org/t/copy-a-dictionary-except-some-keys/2559/5 - Tuukka Mustonen

1

你的一行代码

my_dict = {"keyA": 1, "keyB": 2, "keyC": 3}
(lambda keyB, keyC, **kw: kw)(**my_dict)

这段代码返回了{'keyA': 1}

虽然不太符合Python的风格和动态性,但是它很简短且有技巧性。它使用了函数参数的字典解包(解构赋值)。

另请参见https://dev59.com/8XA85IYBdhLWcg3wEPRL#53851069


1

对于那些不喜欢列表推导式的人,这是我的版本:

def without_keys(d, *keys):
     return dict(filter(lambda key_value: key_value[0] not in keys, d.items()))

使用方法:

>>> d={1:3, 5:7, 9:11, 13:15}
>>> without_keys(d, 1, 5, 9)
{13: 15}
>>> without_keys(d, 13)
{1: 3, 5: 7, 9: 11}
>>> without_keys(d, *[5, 7])
{1: 3, 13: 15, 9: 11}

3
对于那些不喜欢列表推导式的人,你应该学习列表推导式。它们非常“Pythonic”,当你最终理解它们时,你会很高兴你花时间去理解它们,否则你就在与语言作斗争。 - run_the_race

0
你可以使用嵌套字典的通用解决方案。
def copy_dict(data, strip_values=False, remove_keys=[]):
    if type(data) is dict:
        out = {}
        for key, value in data.items():
            if key not in remove_keys:
                out[key] = copy_dict(value, strip_values=strip_values, remove_keys=remove_keys)
        return out
    else:
        return [] if strip_values else data

这个递归解决方案适用于嵌套字典,并从整个嵌套结构中删除不需要的键。它还使您能够仅返回具有键而没有值的嵌套。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接