简体   繁体   中英

How to merge a list of dict to one dict

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}
}
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
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!

如果您有一个简单的字典,则可以执行以下操作:

reduce(lambda a, b: dict(a, **b), list_of_dicts)
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}}}

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}}}
 """

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM