使用字典推导式在Python中删除多个键值对项

3

我想从我的json中删除多个键,我正在使用字典推导式,如下所示:

remove_key = ['name', 'description']

    data = {'full-workflow': {'task_defaults': {'retry': {'count': 3, 'delay': 2}}, 'tasks': {'t1': {'action': 'nn.postgres.export-db', 'description': 'Dump prod DB with default settings', 'input': {'database': 'prod', 'filepath': '/var/tmp/prod-dump.pgsql', 'host': 'postgres.local', 'password': 'mypass', 'username': 'myuser'}, 'name': 'db export', 'on-success': ['t2']}, 't2': {'action': 'nn.aws.upload-to-s3', 'description': 'Upload to S3 bucket for development', 'input': {'sourcepath': '{{ tasks(t1).result.filepath }}', 'targetpath': 's3://mybucket/prod-dump.pgsql'}, 'name': 'Upload to S3', 'on-success': ['t3'], 'retry': {'count': 5, 'delay': 5}}, 't3': {'action': 'nn.shell.command', 'description': 'Remove temp file from batch folder ', 'input': {'cmd': 'rm {{ tasks(t1).result.filepath }}'}, 'name': 'Remove temp file', 'on-complete': ['t4']}, 't4': {'action': 'nn.notify.send-mail', 'description': 'Send email to admin containing target path', 'input': {'from': 'bot@nn.io', 'message': 'DB Dump {{ tasks(t1).result.filepath }} was stored to S3', 'subject': 'Prod DB Backup', 'to': 'admin@nn.io'}, 'name': 'Send email', 'target': 'nn'}}}, 'version': '2'}

    def remove_additional_key(data):
        return {
            key: data[key] for key in data if key not in remove_key
        }

那么就请。
new_data = remove_additional_key(data)

因为这是嵌套字典,我想从“任务”字典中删除“remove_key”,那么我做错了什么?

你的主要“data”字典中嵌套了几个字典。 “name”和“description”是其中一个内部字典中的键,这就是它们没有被删除的原因。 - yuvgin
你的字典只有两个键,你正在迭代它们,分别是 full-workflowversion - jordanm
啊,好的,所以嵌套字典,回到起点重新设计。 - copser
@PetarP 如果您已经清楚了解您所需的操作,您可以编辑您的问题。您是否希望在任何嵌套字典中,如果namedescription是键,则将它们删除? - yuvgin
@yuvgin 我想从“tasks”中删除它们。 - copser
2个回答

2

你的数据是嵌套字典。如果你想删除任何包含在remove_key中的键的数据,那么我建议采用递归方法。基于你现有的函数remove_additional_key,这可以很容易地实现:

最初的回答:

如果您希望删除包含在remove_key中的任何键的数据,则建议使用递归方法。根据您现有的remove_additional_key函数,可以轻松实现此目标。

def remove_additional_key(data):

    sub_data = {} 
    for key in data:
        if key not in remove_key:
            if isinstance(data[key], dict): # if is dictionary
                sub_data[key] = remove_additional_key(data[key])
            else:
                sub_data[key] = data[key]
    return sub_data

new_data = remove_additional_key(data)

注意,如果一个条目是一个字典,可以通过isinstance(data[key], dict)进行检查。请参阅如何在Python中检查变量是否为字典? 。最初的回答。

isinstance 就可以了,不需要用 type ,但这会删除整个字典。 - copser
我进行了测试,当我将我的字典传入函数时,输出的字典为空。 - copser
是的,我已经检查过了,感谢您的更改,您很快 :) - copser
@PetarP 不用谢。但请注意,您也应该考虑其他答案的建议。 - Rabbid76
1
我会的,Alex的建议已经被记录了,问题是我需要做更多的清理工作,但至少我有一个不错的基础可以使用。 - copser

1

如果您有一个带有几个嵌套字典的字典。如果您确切地知道要删除哪些键的子字典,可以使用以下方法:

data['full-workflow']['tasks']['t1'].pop('name')

在字典推导中使用查找方法(key: data[key])是低效的,但是,在如此小的数据量上,您不会注意到差异。
如果您不知道嵌套字典的确切路径,可以使用一个函数(为了方便,另外发布答案)。
def delete_keys_from_dict(d, lst_keys):
    for k in lst_keys:
        try:
            del dict_del[k]
        except KeyError:
            pass
    for v in dict_del.values():
        if isinstance(v, dict):
            delete_keys_from_dict(v, lst_keys)

    return dict_del

那么你可以调用

delete_keys_from_dict(data, ['name', 'description'])

不用多说,如果你在多个嵌套字典中都有name键,则所有这些键都将被删除,所以请小心。


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