Home > Net >  Replace all the keys in nested dictionary and merge duplicate keys in python
Replace all the keys in nested dictionary and merge duplicate keys in python

Time:12-15

I have a nested dictionary that represents parent-child relationships. For example:

{
    "45273425f5abc05b->s": 
        {
            "12864f455e7c86bb->s": {
                "12864f455e7c86bbexternal_call->c": {}
            }
        },
    "c69aead72fcd6ec1->d": 
        {
            "8ade76728bdddf27->d": {
                "8ade76728bdddf27external_call->i": {}
            },
            "b29f07de47c5841f->d": {
                "107bec1baede1bff->l": {
                    "e14ebabea4785c3f->l": {
                        "e14ebabea4785c3fexternal_call->r": {}
                    },
                    "e36b35daa794bd50->l": {
                        "e36b35daa794bd50external_call->a": {}
                    }
                },
                "b29f07de47c5841fexternal_call->l": {}
            },
            "1906ef2c2897ac01->d": {
                "1906ef2c2897ac01external_call->e": {}
            }
        }
}

I want to do two things with this dictionary. Firstly I want to remove everything before and including "->" i.e I want to update the keys. Secondly, after renaming there will be duplicate values in the nested dictionary. for example the second element in the dictionary. If there are two keys with the same name I want to merge them into one. So, the result will look like the following:

{
"s": 
    {
        "s": {
            "c"
        }
    },
"d": 
    {
        "d": {
            "i",
            "l": {
                "l": {
                    "r",
                    "a"
                }
            },
            "e"
        }
    }
}

How can I achieve this? I have written this code so far.

    def alter_dict(nested_dict):
        new_dict = {}
        for k, v in nested_dict.items():
            if isinstance(v, dict):
                v = alter_dict(v)
            new_key = k.split("->")[1]
            new_dict[new_key] = v
        return new_dict

It works for a simple one like the first element but doesn't work for the second one. It loses some information. The purpose of this is to create a graph with the dictionary.

CodePudding user response:

You can use recursion:

import json
from collections import defaultdict
def merge(d):
  r = defaultdict(list)
  for i in d:
    for a, b in i.items():
      r[a.split('->')[-1]].append(b)
  return {a:merge(b) for a, b in r.items()}

data = {'45273425f5abc05b->s': {'12864f455e7c86bb->s': {'12864f455e7c86bbexternal_call->c': {}}}, 'c69aead72fcd6ec1->d': {'8ade76728bdddf27->d': {'8ade76728bdddf27external_call->i': {}}, 'b29f07de47c5841f->d': {'107bec1baede1bff->l': {'e14ebabea4785c3f->l': {'e14ebabea4785c3fexternal_call->r': {}}, 'e36b35daa794bd50->l': {'e36b35daa794bd50external_call->a': {}}}, 'b29f07de47c5841fexternal_call->l': {}}, '1906ef2c2897ac01->d': {'1906ef2c2897ac01external_call->e': {}}}}
print(json.dumps(merge([data]), indent=4))

Output:

{
    "s": {
        "s": {
            "c": {}
        }
    },
    "d": {
        "d": {
            "i": {},
            "l": {
                "l": {
                    "r": {},
                    "a": {}
                }
            },
            "e": {}
        }
    }
}
  • Related