如何从多维(深度未知)python字典中递归删除某些键?

Mar*_*ark 4 python

我在我的一个项目中使用kendoUI Grid。我使用他们的api检索了一段数据,发现它向json / dictionary添加了一些“不需要的”数据。将json传递回我的Pyramid后端后,我需要删除这些键。问题是,字典的深度可以是任意的,而我事先不知道深度。

例:

product = {
    id: "PR_12"
    name: "Blue shirt",
    description: "Flowery shirt for boys above 2 years old",
    _event: {<some unwanted data here>},
    length: <some unwanted data>,
    items: [{_event: {<some rubbish data>}, length: <more rubbish>, price: 23.30, quantity: 34, color: "Red", size: "Large"}, {_event: {<some more rubbish data>}, length: <even more rubbish>, price: 34.50, quantity: 20, color: "Blue", size: "Large"} ....]
}
Run Code Online (Sandbox Code Playgroud)

我要特别删除两个键:“ _ event”和“ length”。我尝试编写一个递归函数来删除数据,但似乎无法正确处理。有人可以帮忙吗?

这是我所拥有的:

def remove_specific_key(the_dict, rubbish):
  for key in the_dict:
    if key == rubbish:
      the_dict.pop(key)
    else:
      # check for rubbish in sub dict
      if isinstance(the_dict[key], dict):
        remove_specific_key(the_dict[key], rubbish)

      # check for existence of rubbish in lists
      elif isinstance(the_dict[key], list):
        for item in the_dict[key]:
          if item == rubbish:
            the_dict[key].remove(item)
   return the_dict
Run Code Online (Sandbox Code Playgroud)

Ned*_*der 5

当你迭代一个字典时修改它是不必要的,因为你确切地知道你正在寻找什么键。另外,您的字典列表没有得到正确处理:

def remove_specific_key(the_dict, rubbish):
    if rubbish in the_dict:
        del the_dict[rubbish]
    for key, value in the_dict.items():
        # check for rubbish in sub dict
        if isinstance(value, dict):
            remove_specific_key(value, rubbish)

        # check for existence of rubbish in lists
        elif isinstance(value, list):
            for item in value:
                if isinstance(item, dict):
                    remove_specific_key(item, rubbish)
Run Code Online (Sandbox Code Playgroud)


unu*_*tbu 5

如果允许remove_specific_key(重命名remove_keys)接受任何对象作为其第一个参数,则可以简化代码:

def remove_keys(obj, rubbish):
    if isinstance(obj, dict):
        obj = {
            key: remove_keys(value, rubbish) 
            for key, value in obj.iteritems()
            if key not in rubbish}
    elif isinstance(obj, list):
        obj = [remove_keys(item, rubbish)
                  for item in obj
                  if item not in rubbish]
    return obj
Run Code Online (Sandbox Code Playgroud)

由于您希望删除多个密钥,因此最好rubbish将其设置为一组而不是一个特定的密钥。使用上面的代码,您将使用以下命令删除“ _event”和“ length”键

product = remove_keys(product, set(['_event', 'length']))
Run Code Online (Sandbox Code Playgroud)

编辑:remove_key使用dict comprehension,在Python2.7中引入。对于旧版本的Python,等效于

    obj = dict((key, remove_keys(value, rubbish))
               for key, value in obj.iteritems()
               if key not in rubbish)
Run Code Online (Sandbox Code Playgroud)