Reputation: 749
I have a list of dict convert from yaml, but how do I merge them to a new one?
I would like to merge this;
ip_service_list = [{'192.168.15.90': {'process': {'nginx': 1}}}, {'192.168.15.90': {'process': {'varnish': 1}}}, {'192.168.15.91': {'process': {'tomcat': 1}}}]
to become this;
{
'192.168.15.90':
{'process': {'nginx': 1,'varnish': 1}}},
'192.168.15.91':
{'process': {'tomcat': 1}
}
Upvotes: 1
Views: 401
Reputation: 8774
If you have a flat dict you can do this:
reduce(lambda a, b: dict(a, **b), list_of_dicts)
Upvotes: 1
Reputation: 17173
Probably a good chance to use itertools.groupby:
_list = [{'192.168.15.90': {'process': {'master': 1}}}, {'192.168.15.90': {'process': {'varnish': 1}}}, {'192.168.15.91': {'process': {'tomcat': 1}}}]
def get_ip(_d):
assert(len(_d.keys())==1)
return _d.keys()[0]
_list.sort(key=get_ip)
from itertools import groupby
result = {}
for k,g in groupby(_list,key=get_ip):
sub_result = {}
for i in g:
v = i[k]
_process = v['process']
assert(len(_process.items())==1)
_process_key,_process_value = _process.items()[0]
assert(_process_key not in sub_result)
sub_result[_process_key] = _process_value
result[k] = {'process': sub_result}
import pprint
pprint.pprint(result)
"""
>>>
{'192.168.15.90': {'process': {'master': 1, 'varnish': 1}},
'192.168.15.91': {'process': {'tomcat': 1}}}
"""
Upvotes: 0
Reputation: 38956
new = {}
old = [{'192.168.15.90': {'process': {'master': 1}}}, {'192.168.15.90': {'process': {'varnish': 1}}}, {'192.168.15.91': {'process': {'tomcat': 1}}}]
def recursive_update(target, source):
for k, v in source.items():
if type(v) == dict:
new = target.setdefault(k,{})
recursive_update(new, v)
else:
target[k] = v
for d in old:
recursive_update(new,d)
print(repr(new))
result:
>> {'192.168.15.91': {'process': {'tomcat': 1}}, '192.168.15.90': {'process': {'varnish': 1, 'master': 1}}}
Upvotes: 0
Reputation: 176750
dictlist = [{'192.168.15.90': {'process': {'master': 1}}},
{'192.168.15.90': {'process': {'varnish': 1}}},
{'192.168.15.91': {'process': {'tomcat': 1}}}]
dd = {
'192.168.15.90':
{'process': {'master': 1,'varnish': 1}},
'192.168.15.91':
{'process': {'tomcat': 1}
}}
new = {}
# for each dict in the list
for dct in dictlist:
# get the ip address
ip, = dct
# if the ip address is already in the new dict
if ip in new:
# copy in the process info
new[ip]['process'].update(dct[ip]['process'])
# if the ip address isn't in the new dict yet
else:
# add the ip address and its info to the new dict
new.update(dct)
print dd == new # True!
Upvotes: 2
Reputation: 107598
from collections import defaultdict
# the structure we try to fill is in the lambda
d = defaultdict(lambda:{'process' : {}})
for row in s:
# just one iteration, aka ip = next(iter(row))
for ip in row:
d[ip]['process'].update(row[ip]['process'])
print d
Upvotes: 3