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

How to recursively remove certain keys from a multi-dimensional(depth not known) python dictionary?

我在我的一个项目中使用了Kendoui网格。我使用他们的API检索到一段数据,发现它在我的JSON/字典中添加了一些"不需要的"数据。在将JSON传递回我的金字塔后端之后,我需要删除这些密钥。问题是,这本词典可以有任何深度,我不知道它的深度。

例子:

1
2
3
4
5
6
7
8
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"} ....]
}

我特别想删除两个键:"u event"和"length"。我试着写一个递归函数来删除数据,但我似乎做不好。有人能帮忙吗?

以下是我的资料:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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


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

1
2
3
4
5
6
7
8
9
10
11
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

因为您希望删除多个密钥,所以您也可以让rubbish是一个集合,而不是一个特定的密钥。使用上面的代码,您将删除"_event"和"length"键,

1
product = remove_keys(product, set(['_event', 'length']))

编辑:remove_key使用听写理解,在python2.7中介绍。对于旧版本的python,等价物是

1
2
3
    obj = dict((key, remove_keys(value, rubbish))
               for key, value in obj.iteritems()
               if key not in rubbish)


在迭代时修改dict,这是不必要的,因为您确切地知道要查找的是什么键。此外,你的口述列表处理不当:

1
2
3
4
5
6
7
8
9
10
11
12
13
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)


迭代时无法删除dict或list,因此请用测试函数替换迭代程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def remove_specific_key(the_dict, rubbish):
    if the_dict.has_key(rubbish):
        the_dict.pop(rubbish)
    else:
        for key in the_dict:
            if isinstance(the_dict[key], dict):
                remove_specific_key(the_dict[key], rubbish)
            elif isinstance(the_dict[key], list):
                if the_dict[key].count(rubbish):
                    the_dict[key].remove(rubbish)
    return the_dict


d = {"a": {"aa":"foobar"}}
remove_specific_key(d,"aa")
print d

d = {"a": ["aa","foobar"]}
remove_specific_key(d,"aa")
print d