python 如何删除字典值只是在一个特定的关键字'路径'?

zxlwwiss  于 2022-11-28  发布在  Python
关注(0)|答案(2)|浏览(117)

我想实现一个函数:
给定一个字典和一个可迭代的键,
删除通过迭代这些键访问的值。
原来我曾经试过

def delete_dictionary_value(dict, keys):

    inner_value = dict
    for key in keys:
        inner_value = inner_value[key]
    del inner_value
    return dict

考虑到inner_value是通过引用赋值给dict的,我们可以通过修改inner_value来简单地修改dict,然而,赋值inner_value本身似乎创建了一个新的引用(通过在循环内赋值inner_value来增加sys.getrefcount(dict[key]))-结果是局部变量赋值是del ed,但dict返回时没有变化。
使用inner_value = None具有相同的效果-大概是因为这仅仅是重新分配inner_value
其他人已经张贴寻找答案的问题,如:

  • 我如何确保我的字典在关键字x处不包含任何值--这可能是一个关于嵌套字典递归的问题,或者
  • 如何迭代给定键的值(这个问题的不同风格)
  • 如何访问键的值而不是字典中的键值

这不是上面的任何一个--我想删除字典中的一个 specific 键,值对,它可能是任意深度的嵌套--但是我总是知道我想删除的键,值对的路径。
到目前为止,我已经破解了以下解决方案:

def delete_dictionary_value(dict, keys):

    base_str = f"del dict"
    property_access_str = ''.join([f"['{i}']" for i in keys])
    return exec(base_str + property_access_str)

这感觉不对。
这看起来也是非常基本的功能--但是我还没有找到一个明显的解决方案。很可能我遗漏了一些东西(很可能是一些非常明显的东西)--请帮我看看。

xam8gpfp

xam8gpfp1#

如果根本不需要进行错误检查,只需迭代到 * 倒数第二个 * 键,然后从那里删除值:

def del_by_path(d, keys):
  for k in keys[:-1]:
    d = d[k]
  return d.pop(keys[-1])

d = {'a': {'b': {'c': {'d': 'Value'}}}}
del_by_path(d, 'abcd')
# 'Value'
print(d)
# {'a': {'b': {'c': {}}}}

为了好玩,这里有一个更“功能化”的方法来做同样的事情:

from functools import reduce
def del_by_path(d, keys):
    *init, last = keys
    return reduce(dict.get, init, d).pop(last)
vptzau2j

vptzau2j2#

不要使用字符串求值的方法。尝试迭代地移动到最后一个字典并删除其中的键-值对。下面是一种可能性:

def delete_key(d, value_path):
    # move to most internal dictionary
    for kp in value_path[:-1]:
        if kp in dd and isinstance(d[kp], dict): 
            d = d[kp]
        else:
            e_msg = f"Key-value delete-operation failed at key '{kp}'"
            raise Exception(e_msg)

    # last entry check
    lst_kp = value_path[-1]
    if lst_kp not in d:
        e_msg = f"Key-value delete-operation failed at key '{lst_kp}'"
        raise Exception(e_msg)

    # delete key-value of most internal dictionary
    print(f'Value "{d[lst_kp]}" at position "{value_path}" deleted')
    del d[lst_kp]

d = {1: 2, 2:{3: "a"}, 4: {5: 6, 6:{8:9}}}

delete_key(d, [44, 6, 0])
#Value "9" at position "[4, 6, 8]" deleted
#{1: 2, 2: {3: 'a'}, 4: {5: 6, 6: {}}}

相关问题