samxiao
samxiao

Reputation: 2667

Merging two list of dictionaries selectively on Python

I have the following code which works, but looks like it's very nested. I am sure there's a better way to write this, but I am also new to using Python's map/filter on lambda. What's a better way to write this to merge 2 dictionaries and only picking on the key we are interested.

import copy

default_params_list = [
    {
        "abc": "some junk that we do not care",
        "time_unit": "week",
        "city": "atlanta"
    }
]

foobar_list = [
    {
        "type": "predict",
        "junk": "something we do not care",
        "start_date": "2018-09-15",
        "length": "all"
    }
]

params_list = []
for foobar in foobar_list:
    for default_params in default_params_list:
        parameters = copy.deepcopy(default_params)
        parameters.update({
            'length': foobar['length']
        })
        if(foobar.get('type', none) == 'predict'):
            if(foobar.get('start_date', none)):
                parameters.update({
                    'start_date': foobar['start_date']
                })
        if(foobar.get('type', none) == 'training'):
            if(foobar.get('end_date', none)):
                parameters.update({
                    'end_date': foobar['end_date']
                })
        params_list.append({
            'parameters': parameters
        })
print(params_list)

output:

[
     {'parameters': 
             {'abc': 'some junk that we do not care', 
              'time_unit': 'week', 
              'city': 'atlanta', 
              'length': 'all', 
              'start_date': '2018-09-15'}
     }
]

Upvotes: 0

Views: 96

Answers (2)

Siva-Sg
Siva-Sg

Reputation: 2821

For Python 2.7 , the following approach works.

full_dict = {}
full_dict_list = [] 
for index,val in enumerate(foobar_list):
  full_dict = dict(default_params_list[index],**val) # merge dictionaries from both the lists
  map(full_dict.pop, ['junk','type']) # remove the unwanted keys
  full_dict_list.append(full_dict)

update: approach without using for loops.

full_dict_list = map(lambda d1,d2:dict(d1.items()+d2.items()),foobar_list,default_params_list)
map(lambda d1:map(d1.pop,['junk','type']), full_dict_list) 

Upvotes: 1

Michael Dorner
Michael Dorner

Reputation: 20175

full_dict = {**default_params_list[0], **foobar_list[0]}
select_dict = {k: full_dict[k] for k in full_dict if k not in ['junk', 'type']}
print(select_dict) # {'abc': 'some junk that we do not care', 'time_unit': 'week', 'city': 'atlanta', 'start_date': '2018-09-15', 'length': 'all'}

Some remark:

  • This works only with Python 3.5 and older I assumed that your focus is on readability and not on performance.
  • In this snippet we first merge both dicts and then removed the unwanted values. Vice versa would be more efficient, but I really like this new feature (PEP 448).
  • Your default_params_list and foobar_list is not a dict, but a list.

Upvotes: 0

Related Questions