1

I have the following nested dict:

 ex_dict = {'path1':
             {'$variable1': '2018-01-01',
              '$variable2': '2020-01-01',
              '$variable3': '$variable1',
              '$variable4': '$variable3'},
            'path2':
             {'$variable1': '2018-01-01',
              '$variable2': '2020-01-01',
              '$variable3': '$variable1',
              '$variable4': '$variable1 + $variable2'}
           }

I want to replace any $variableX specified for a dict key with the dict value from another key if the key from the other dict value if found in the value of the original dict key. See example output below:

{'path1':
         {'$variable1': '2018-01-01',
          '$variable2': '2020-01-01',
          '$variable3': '2018-01-01',  # Substituted with value from key:variable1
          '$variable4': '2018-01-01'}, # Substituted with value from key:variable3 (after variable3 was substituted with variable1)    
 'path2':
         {'$variable1': '2018-01-01',
          '$variable2': '2020-01-01',
          '$variable3': '2018-01-01',  # Substituted with value from key:variable1
          '$variable4': '2018-01-01 + 2020-01-01'} # Substituted with value from key:variable3 (after variable3 was substituted with variable1) and key:variable2
       }  

Does anyone have any suggestions?

3 Answers3

2

You could do replacement by recursively walking through the dict and using the re library to do the replacements

import re

def process_dict(d):
    reprocess = []
    keys = d.keys()
    while keys:
        for k in keys:
            v = d[k]
            if isinstance(v, dict):
                process_dict(v)
            elif '$' in v:
                d[k] = re.sub(r'\$\w+', lambda m: d[m.group(0)] if m.group(0) in d else m.group(0), v)
                if '$' in d[k] and d[k] != v:
                    reprocess.append(k)
        keys = reprocess
        reprocess = []

Edit:

I added a reprocessing step to handle the cases where the references are chained and require multiple passes through some keys in the dictionary to fully process them.

Brendan Abel
  • 35,343
  • 14
  • 88
  • 118
1

Not a very Pythonic solution, but, does the trick:

ex_dict = {'path1':
               {'$variable1': '2018-01-01',
                '$variable2': '2020-01-01',
                '$variable3': '$variable1',
                '$variable4': '$variable3'},
           'path2':
               {'$variable1': '2018-01-01',
                '$variable2': '2020-01-01',
                '$variable3': '$variable1',
                '$variable4': '$variable1 + $variable2'}
           }

for path, d in ex_dict.items():
    for k, v in d.items():
        if v.startswith('$variable'):
            try:
                if '+' in v:
                    ex_dict[path][k] = ' + '.join(ex_dict[path][x.strip()] for x in v.split('+'))
                else:
                    ex_dict[path][k] = ex_dict[path][v]
            except KeyError:
                pass

pprint(ex_dict)

Output:

{'path1': {'$variable1': '2018-01-01',
           '$variable2': '2020-01-01',
           '$variable3': '2018-01-01',
           '$variable4': '2018-01-01'},
 'path2': {'$variable1': '2018-01-01',
           '$variable2': '2020-01-01',
           '$variable3': '2018-01-01',
           '$variable4': '2018-01-01 + 2020-01-01'}}
Keyur Potdar
  • 7,158
  • 6
  • 25
  • 40
0

You can use a dictionary comprehension:

import re
dict = {'path1':
     {'$variable1': '2018-01-01',
      '$variable2': '2020-01-01',
      '$variable3': '$variable1',
      '$variable4': '$variable3'},
    'path2':
     {'$variable1': '2018-01-01',
      '$variable2': '2020-01-01',
      '$variable3': '$variable1',
      '$variable4': '$variable1 + $variable2'}
   }

final_data = {a:{c:d if re.findall('\d+-\d+-\d+', d) else \
re.sub('\$\w+', '{}', d).format(*[b[i] for i in re.findall('\$\w+', d)]) \
 for c, d in b.items()} for a, b in dict.items()}

Output:

{'path2': {'$variable4': '2018-01-01 + 2020-01-01', '$variable2': '2020-01-01', '$variable3': '2018-01-01', '$variable1': '2018-01-01'}, 'path1': {'$variable4': '$variable1', '$variable2': '2020-01-01', '$variable3': '2018-01-01', '$variable1': '2018-01-01'}}
Ajax1234
  • 69,937
  • 8
  • 61
  • 102