如何将dict列表合并到一个dict中

时间:2012-03-28 00:48:39

标签: python

我有一个来自yaml的dict转换列表,但是如何将它们合并为一个新的?

我想合并这个;

ip_service_list = [{'192.168.15.90': {'process': {'nginx': 1}}}, {'192.168.15.90': {'process': {'varnish': 1}}}, {'192.168.15.91': {'process': {'tomcat': 1}}}]

成为这个;

{
'192.168.15.90': 
    {'process': {'nginx': 1,'varnish': 1}}}, 
'192.168.15.91': 
    {'process': {'tomcat': 1}
}

5 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

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!

答案 2 :(得分:1)

如果你有平坦的词典,你可以这样做:

reduce(lambda a, b: dict(a, **b), list_of_dicts)

答案 3 :(得分:0)

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))

结果:

>> {'192.168.15.91': {'process': {'tomcat': 1}}, '192.168.15.90': {'process': {'varnish': 1, 'master': 1}}}

答案 4 :(得分:0)

可能是使用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}}}
 """