从嵌套字典中动态删除一个项目

7

我是一名有用的助手,可以为您进行文本翻译。

我有一个嵌套字典,并希望能够删除其中任意一个键。

该字典可能如下所示:

D={'key1':{'key2':{'key3':'value3', 'key4':'value4'}, 'key5':'value5'}}

但它可以是任意大小的。问题在于密钥应该从“密钥列表”中获取,例如:

key_list = ['key1', 'key2', 'key4']
key_list 可以是任意大小,并且可以包含字典中的任何键。
由于以上条件,我不能仅仅使用以下代码:
del D['key1']['key2']['key4']

因为我无法预先知道 key_list 包含哪些键。

那么,基于 key_list 的内容,一个通用的代码应该如何删除字典 D 中相应的项?


你确定你的 key_list 的顺序吗?如果你想删除相应的项,它不会引发 KeyError 异常! - Mazdak
没有KeyError的我。 - PandaDeTapas
可能会澄清我的问题的两个问题是:1)每次的意图是从字典中删除单个键/值对吗?2)键在key_list中出现的顺序是否重要?我想第二个问题很像@Kasra所问的。 - rchang
在您的例子中,您是打算将键作为字典中深度嵌套元素的路径,因此只删除叶子吗?还是您打算删除键列表中给出的每个元素? - Meitham
还有一个问题 - 字典中的不同键是否可以多次出现(在不同的“级别”中)?例如,D = {'key1':{'key1':'value1', 'key2':'value2'}} - rchang
非常抱歉我没有表达清楚。我的意思是删除单个键/值对,即最内部的键或“叶子”,正如@Meitham所说的那样。key_list中的顺序很重要,它是字典中键的顺序。不同的键可以多次出现,但如果这不可能,我将感激任何其他解决方案的尝试。 - PandaDeTapas
3个回答

7
你可以使用for循环遍历key_list中的值,并导航到你想要从中删除项的子字典:
sub = D                 # Start with the full dictionary
for i in key_list[:-1]:
    sub = sub[i]        # Move down a level

最终,sub 将是您想要更改的字典。现在您需要做的就是:
del sub[key_list[-1]]

由于key_list[-1]是需要移除的键。

以下是演示:

>>> D={'key1':{'key2':{'key3':'value3', 'key4':'value4'}, 'key5':'value5'}}
>>> key_list = ['key1', 'key2', 'key4']
>>> sub = D
>>> for i in key_list[:-1]:
...     sub = sub[i]
...
>>> del sub[key_list[-1]]
>>> D
{'key1': {'key5': 'value5', 'key2': {'key3': 'value3'}}}
>>>

如您所见,这等同于:

>>> D={'key1':{'key2':{'key3':'value3', 'key4':'value4'}, 'key5':'value5'}}
>>> del D['key1']['key2']['key4']
>>> D
{'key1': {'key5': 'value5', 'key2': {'key3': 'value3'}}}
>>>

除了解决方案是动态的(没有硬编码键)之外,与此相同。


看起来运行得很好!我没有意识到子程序可以影响D,这是个不错的解决方案。 - PandaDeTapas

0
您可以将嵌套字典看作具有多部分键的字典。如果您转换字典,则可以决定何时删除元素。如果键的一部分在键列表中或满足任何其他条件,那么请考虑以下内容:
D={'key1':{'key2':{'key3':'value3', 'key4':'value4', 'key7':{'key8':'value8'}}, 'key5':'value5'}, 'key6': 'value6'}

def multipart_key(d):
    dd = {}
    for k in d:
        if isinstance(d[k], dict):
            inner = multipart_key(d[k])
            for kk in inner:
                dd[k+chr(124)+kk] = inner[kk]
        else:
            dd[k] = d[k]
    return dd

key_list = ['key3', 'key7']

DD = multipart_key(D)
newDD = DD.copy()

for k in DD:
    for kk in k.split(chr(124)):
        if kk in key_list:
            del newDD[k]
            break

print(DD)
# {'key1|key2|key3': 'value3', 'key1|key5': 'value5', 'key6': 'value6', 'key1|key2|key7|key8': 'value8', 'key1|key2|key4': 'value4'}

print(newDD)
# {'key1|key5': 'value5', 'key6': 'value6', 'key1|key2|key4': 'value4'}

0
如果您使用 NestedDict,您可以像在扁平的字典中一样弹出或删除任何键。
首先让我们初始化一个:
from ndicts.ndicts import NestedDict

d = {'key1': {'key2': {'key3': 'value3', 'key4': 'value4'}, 'key5': 'value5'}}
nd = NestedDict(d)
key = ('key1', 'key2', 'key4')

选项1

>>> del nd[key]

选项2

>>> nd.pop(key)
'value4'

请注意,这将删除原始字典中的一项。为了避免这种情况,在实例化 NestedDict 时可以进行复制。
nd = NestedDict(d, copy=True)

安装ndicts,请执行pip install ndicts


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