2

I have to different nested dict and I want to replace some keys in dict A with corresponding values in dict B Here is dict A

{
  "Animals": {
    "catgry": {
      "1": "Dogs",
      "2": "Cats",
      "3": "Birds",
    }
  },
  "dogBreeds": {
    "catgry": {
      "1": "Belgian Malinois",
      "2": "Australian Bulledog",
      "3": "Cane Corso",
      "4": "Chow chow",
      "5": "Dalmatian",
      "6": "Dobermann",
      "7": "Labrador",
      "8": "Rottweiler"
    }
  }
}

and the dict B is

{
  "name": "MyGarden",
  "children": [
    {
      "name": "Animals",
      "Animals":"1",
      "children": [
        {
          "name": "dogBreeds",
          "dogBreeds":"1",
          "children": [
            {
              "name": "myBelgian malinois",
              "weight": "30"
            }
          ]
        },
        {
          "name": "dogBreeds",
          "dogBreeds":"2",
          "children": [
            {
              "name": "myAustralian Bulledog",
              "weight": "35"
            }
          ]
        }
      ]
    }
  ]
}

I tried first to remove the key 'catgry' from dict A and then replace the values with the corresponding key but didn't succeed without deleting the children also

[EDIT] Here is the expected result

{
  "name": "MyGarden",
  "children": [
    {
      "Animals":"Dogs",
      "children": [
        {
          "dogBreeds":"Belgian Malinois",
          "children": [
            {
              "name": "myBelgian malinois",
              "weight": "30"
            }
          ]
        },
        {
          "dogBreeds":"Australian Bulledog",
          "children": [
            {
              "name": "myAustralian Bulledog",
              "weight": "35"
            }
          ]
        }
      ]
    }
  ]
}
didoo14
  • 57
  • 9

3 Answers3

1

You need to create a new entry FIRST and then delete the old entry. Change the name of a key in dictionary

EchoCloud
  • 61
  • 5
  • That does not resolve my problem, my dict is nested plus I want to replace multiple keys – didoo14 May 14 '19 at 14:33
  • You're creating a new dictionary entry FIRST with the dictionary information you want to preserve and then deleting the old dictionary entry. You can't change existing dictionary keys. I've only ever seen people generate new entries and delete old ones--I've never seen people change existing dictionary keys. – EchoCloud May 14 '19 at 14:38
  • As for nesting. You merely need to traverse through the dictionary structure to grab the data you want to generate the new key:value pair at each branch. https://stackoverflow.com/questions/10756427/loop-through-all-nested-dictionary-values – EchoCloud May 14 '19 at 14:42
0

So I am making a few assumptions here about what types your nested dictionary will contain, and the presence of the catgry subdicts.

However you should be able to solve this with recursion.

def val_replace(dictb, refdict):
    for k, v in dictb.items():
        if k in refdict:
            dictb[k] = refdict[k]['catgry'][v]
        elif isinstance(v, dict):
            val_replace(v, refdict)
        elif isinstance(v, list):
            for v2 in v:
                if isinstance(v2, dict):
                    val_replace(v2, refdict)

myref = {
  "Animals": {
    "catgry": {
      "1": "Dogs",
      "2": "Cats",
      "3": "Birds",
    }
  },
  "dogBreeds": {
    "catgry": {
      "1": "Belgian Malinois",
      "2": "Australian Bulledog",
      "3": "Cane Corso",
      "4": "Chow chow",
      "5": "Dalmatian",
      "6": "Dobermann",
      "7": "Labrador",
      "8": "Rottweiler"
    }
  }
}

mydict = {
  "name": "MyGarden",
  "children": [
    {
      "name": "Animals",
      "Animals":"1",
      "children": [
        {
          "name": "dogBreeds",
          "dogBreeds":"1",
          "children": [
            {
              "name": "myBelgian malinois",
              "weight": "30"
            }
          ]
        },
        {
          "name": "dogBreeds",
          "dogBreeds":"2",
          "children": [
            {
              "name": "myAustralian Bulledog",
              "weight": "35"
            }
          ]
        }
      ]
    }
  ]
}

val_replace(mydict, myref)

And the result is:

{
    'name': 'MyGarden', 
    'children': [
        {
         'name': 'Animals', 
         'Animals': 'Dogs', 
         'children': [
             {
              'name': 'dogBreeds', 
              'dogBreeds': 'Belgian Malinois', 
              'children': [
                  {'name': 'myBelgian malinois', 'weight': '30'}
              ]
             }, 
            {
             'name': 'dogBreeds', 
             'dogBreeds': 'Australian Bulledog', 
             'children': [
                  {'name': 'myAustralian Bulledog', 'weight': '35'}
             ]
            }
          ]
         }
     ]
}
PyPingu
  • 1,697
  • 1
  • 8
  • 21
0

You can use recursion:

a = {'Animals': {'catgry': {'1': 'Dogs', '2': 'Cats', '3': 'Birds'}}, 'dogBreeds': {'catgry': {'1': 'Belgian Malinois', '2': 'Australian Bulledog', '3': 'Cane Corso', '4': 'Chow chow', '5': 'Dalmatian', '6': 'Dobermann', '7': 'Labrador', '8': 'Rottweiler'}}}
b = {'name': 'MyGarden', 'children': [{'name': 'Animals', 'Animals': '1', 'children': [{'name': 'dogBreeds', 'dogBreeds': '1', 'children': [{'name': 'myBelgian malinois', 'weight': '30'}]}, {'name': 'dogBreeds', 'dogBreeds': '2', 'children': [{'name': 'myAustralian Bulledog', 'weight': '35'}]}]}]}
def rename(d):
  return {**d, 'children':list(map(rename, d.get('children', [])))} if d['name'] not in a else \
      {d['name']:a[d['name']]['catgry'][d[d['name']]], 'children':list(map(rename, d.get('children', [])))}

Output:

{
  "name": "MyGarden",
  "children": [
    {
        "Animals": "Dogs",
        "children": [
            {
                "dogBreeds": "Belgian Malinois",
                "children": [
                    {
                        "name": "myBelgian malinois",
                        "weight": "30",
                        "children": []
                    }
                ]
            },
            {
                "dogBreeds": "Australian Bulledog",
                "children": [
                    {
                        "name": "myAustralian Bulledog",
                        "weight": "35",
                        "children": []
                    }
                ]
            }
        ]
      }
   ]
}
Ajax1234
  • 69,937
  • 8
  • 61
  • 102