Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to grow a nested dictionary by adding more key:value pairs

I am facing some trouble with trying to add more key:value pairs to a dictionary object that is itself nested within another dictionary object. Also, the usual way of doing dict[key] = value to assign additional key:value pairs to the dictionary is not suitable for my case here (I'll explain why later below), and thus this makes my objective a lot more challenging to achieve.

I'll illustrate what I'm trying to achieve with some statements from my source code.

First, I have a dictionary object that contains nesting:

environment = { 'v' : 
                  {
                   'SDC_PERIOD':'{period}s'.format(period = self.period),
                   'FAMILY':'{legup_family}s'.format(legup_family = self.legup_family),
                   'DEVICE_FAMILY':'"{fpga_family}s"'.format(fpga_family = self.fpga_family)
                   }
              }

and then following this line, I will do an if test that, if passed, will require me to add this other dictionary:

environment_add = { 'v' : {'LM_LICENSE_FILE' : '1800@adsc-linux'} , 
                    'l' : 'quartus_full' }

to ultimately form this complete dictionary:

environment = { 'v' : 
                  {
                   'SDC_PERIOD':'{period}s'.format(period = self.period),
                   'FAMILY':'{legup_family}s'.format(legup_family = self.legup_family),
                   'DEVICE_FAMILY':'"{fpga_family}s"'.format(fpga_family = self.fpga_family),
                   'LM_LICENSE_FILE' : '1800@adsc-linux'
                   } ,
                'l' : 'quartus_full'
              }

As you can see, if I were to try and assign a new key:value pair using the dict[key] = value syntax, it would not work for me because it would end up either creating an new key:value pair for me, or overwrite the existing dictionary object and the key:value pairs that are nested under the 'v' key.

So far, in order to accomplish the creation of the dictionary, I've been using the following:

environment = """{ v: {'SDC_PERIOD':'%(period)s','FAMILY':'%(legup_family)s','DEVICE_FAMILY':'"%(fpga_family)s"'}}""" % self
if self.require_license:  # this is the if statement test that I was referring to earlier
  environment = environment.replace('}', '')
  environment += """ ,'LM_LICENSE_FILE':'1800@adsc-linux'}, 'l': 'quartus_full'}"""

and then obtaining the dictionary object later with:

import ast
env_dict = ast.literal_eval(environment)

which gives effectively converts the environment string into a dictionary object stored under a new variable name of env_dict.

My teammates think that this is much too overkill, especially since the environment or env_dict object will be parsed in 2 separate modules later on. In the first module, the key-value pairs will be broken up and reconstructed to form strings that look like '-v SDC_PERIOD=2500s, LM_LICENSE_FILE=1800@adsc-linux' , while in the second module, the dictionary nested under the 'v' key (of the environment/env_dict dictionary object) will be extracted out and directly fed as an argument to a function that accepts a mapping object.

So as you can see, there is quite a lot of precise parsing required to do the job, and although my method fulfills the objective, it is not accepted by my team and they think that there must be a better way to do this directly from environment being a dictionary object and not a string object.

Thank you very much for studying my detailed post, and I will greatly appreciate any help or suggestions to move forward on this!

like image 377
AKKO Avatar asked Nov 10 '14 08:11

AKKO


2 Answers

for k,v in environment_add.iteritems(): # .items() in Python 3
    if k in environment:
        environment[k].update(v)
    else:
        environment[k] = v

That is, for each item to add, check if it exists, and update it if so, or simply create it. This assumes the items being added, if they exist, will be dicts (you can't update a string like quartus_full).

like image 190
John Zwinck Avatar answered Nov 15 '22 01:11

John Zwinck


Why not just use update

In [4]: dict_ = {"a": {"b": 2, "c": 3}}

In [5]: dict_["a"].update(d=4)

In [6]: dict_
Out[6]: {'a': {'b': 2, 'c': 3, 'd': 4}}
like image 22
Greg Avatar answered Nov 14 '22 23:11

Greg