1

Looking for a generic solution where I can remove the specific key and its value from dict. For example, if dict contains the following nested key-value pair:

data={

  "set": {
  "type": "object", #<-- should remove this key:value pair
  "properties": {
    "action": {
      "type": "string",  #<-- should NOT remove this key:value pair
      "description": "My settings"
    },
    "settings": {
      "type": "object", #<-- should remove this key:value pair
      "description": "for settings",
      "properties": {
        "temperature": {
          "type": "object", #<-- should remove this key:value pair
          "description": "temperature in degree C",
          "properties": {
            "heater": {
              "type": "object", #<-- should remove this key:value pair
              "properties": {
                "setpoint": {
                  "type": "number"
                },
              },
              "additionalProperties": false
            },

          },
          "additionalProperties": false
        },

      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
}

I want an output dict without "type":"object" across the occurrence of this key:value pair. The expected output should produce the result without "type":"object"

  • To remove an element of a dictionary you may have a look at [https://stackoverflow.com/questions/5844672/delete-an-element-from-a-dictionary](https://stackoverflow.com/questions/5844672/delete-an-element-from-a-dictionary) For your typical problem, you may use recursive functions – Romain F Nov 19 '19 at 16:25
  • 1
    Here's a general purpose recursive dictionary search https://stackoverflow.com/questions/14962485/finding-a-key-recursively-in-a-dictionary – Simon Notley Nov 19 '19 at 16:28

3 Answers3

7

You can write a recursive function:

def remove_a_key(d, remove_key):
    if isinstance(d, dict):
        for key in list(d.keys()):
            if key == remove_key:
                del d[key]
            else:
                remove_a_key(d[key], remove_key)

and call it as:

remove_a_key(data, 'type')

This recursively removes 'type' key and it's value from each nested dictionary no matter how deep it is.

Austin
  • 25,759
  • 4
  • 25
  • 48
  • Your logic remove all occurrences of key 'type'. This means the logic removes `type:'object'` which is expected but it also removes `type':'string'` which is not an expected result. Hope I made it clear on the requirement. – shekar chandra Nov 20 '19 at 12:20
  • Thanks for the logic. Modified to meet my requirement. Please review the modified logic. ```def remove_a_key(d, remove_key, remove_val): if isinstance(d, dict): for key in list(d.keys()): if key == remove_key and d[key] == remove_val: del d[key] else: remove_a_key(d[key], remove_key,remove_val) import json with open('test.json') as f: myjson = json.load(f) path = [] remove_a_key(myjson, 'type','string')``` – shekar chandra Nov 20 '19 at 12:34
  • @shekarchandra, Your code looks fine. Maybe I read wrong, I answered for the removal of all keys without taking values into consideration. But hope my answer was helpful. Kindly, accept a helpful answer from the two already posted by clicking a tick on the left of the answer (This helps the community identify the helpful solution). Thanks. – Austin Nov 20 '19 at 16:12
1

Use python module nested-lookup to play with any kind of nested documents. Checkout https://pypi.org/project/nested-lookup/ for more info.

In your case you need to use method nested_delete to delete all occurrences of a key.

Usage:

from nested_lookup import nested_delete

print(nested_delete(data, 'type'))
Ramesh RV
  • 72
  • 7
0

I get the following error with the recurcive function :

for key in list(d.keys()): TypeError: 'dict' object is not callable

  • 1
    This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). – Flair Aug 27 '21 at 23:51
  • Please provide additional details in your answer. As it's currently written, it's hard to understand your solution. – Community Aug 28 '21 at 03:24