2012-03-28 153 views
1

我有一个从yaml字典转换的列表,但我如何将它们合并到一个新的?如何合并一个字典的列表为一个字典

我想合并这个;

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

回答

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! 
+0

很酷,以前没见过ip,= dct。究竟是如何工作的 – 2012-03-28 01:13:31

+1

@robertking'dct'是一个可迭代的,它给你自己的关键。 'ip,'意思是“解开长度为1的迭代器,并将第一个项目放在”ip“中 - 它只是一个元素的开包,因为'dct'只有一个键,这是一个很好的捷径,你也可以使用'ip = next(iter(dct))'或'ip = dct.keys()[0]'。 – agf 2012-03-28 01:18:11

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}}} 
+1

{ '192.168.15.90':{ '过程':{ '清漆':1}}, '192.168.15.91':{ '过程':{ 'Tomcat的':1}}}丢失了一些数值 – znetor 2012-03-28 00:54:53

+1

不,这会在'192.168.15.90'上消失。 – 2012-03-28 00:55:00

+0

是啊没有注意到重复键,更新为使用递归 – SpliFF 2012-03-28 01:06:04

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

做此:

reduce(lambda a, b: dict(a, **b), list_of_dicts) 
相关问题