将2个dicts列表合并为一个

时间:2017-03-11 17:43:44

标签: python list dictionary

我有两个词组列表:

rds_detail:

[   {   'rds_name': u'emsclassicldap', 'rds_type': u'db.m3.medium'},
    {   'rds_name': u'fra01-devops-KPX', 'rds_type': u'db.t2.medium'},
    {   'rds_name': u'prodreplica', 'rds_type': u'db.t2.medium'}
]

cloudwatch_detail:

[   {   'alarm_name': u'emsclassicldap_db_connections', 'alarm_threshold': 380.0},
    {   'alarm_name': u'fra01-devops-KPX_db_connection',
        'alarm_threshold': 266.0},
    {   'alarm_name': u'prodreplica_db_connections',
        'alarm_threshold': 266.0},
]

alarm_name实际上有rds_name作为其子字符串;我需要根据这个条件将这两个列表合并为一个,以便最终结果看起来像

[
    {   'rds_name': u'emsclassicldap', 'rds_type': u'db.m3.medium','alarm_name': u'classicldap_db_connections', 'alarm_threshold': 380.0}
    .
    .
    So on
    . 
    .
]

我正在写一个简单的def来结合:

def combine_rds_cloudwatch(rds_detail,cloudwatch_detail):
    print rds_detail,cloudwatch_detail

    for rds in rds_detail:
        for alarm in cloudwatch_detail:
            if ????????????

不知道该怎么做

4 个答案:

答案 0 :(得分:2)

而且,dict(one_dict, **other_dict)会为您提供另一个字典,其中包含两个词典中的项目:

>>> d1 = {'a': 1, 'b': 2}
>>> d2 = {'c': 3, 'd': 4}
>>> dict(d1, **d2)  # => dict({'a':1,'b':2}, c=3, d=4)
{'a': 1, 'c': 3, 'b': 2, 'd': 4}

您可以使用list comprehension(两个for子句)制作产品并使用if子句过滤它们:

def combine_rds_cloudwatch(rds_detail,cloudwatch_detail):
    return [dict(rds, **alarm) for rds in rds_detail
                               for alarm in cloudwatch_detail
                               if rds['rds_name'] in alarm['alarm_name']]
                          # OR if alarm['alarm_name'].startswith(rds['rds_name'])

答案 1 :(得分:2)

更通用的方法..

rds_list = [{'rds_name': u'emsclassicldap', 'rds_type': u'db.m3.medium'},
            {'rds_name': u'fra01-devops-KPX', 'rds_type': u'db.t2.medium'},
            {'rds_name': u'goldenprodreplica', 'rds_type': u'db.t2.medium'}
            ]

cloudwatch_list = [{'alarm_name': u'emsclassicldap_db_connections', 'alarm_threshold': 380.0},
                   {'alarm_name': u'fra01-devops-KPX_db_connection', 'alarm_threshold': 266.0},
                   {'alarm_name': u'goldenprodreplica_db_connections', 'alarm_threshold': 266.0},
                   ]


def merge_two_dicts(x, y):
    """Given two dicts, merge them into a new dict as a shallow copy.
       More info here http://stackoverflow.com/questions/38987/how-to-merge-two-python-dictionaries-in-a-single-expression?rq=1
    """
    z = x.copy()
    z.update(y)
    return z


def combine_list(prefix_key_list, prefix_key, keys_list, key):
    combined_list = []

    for short in prefix_key_list:
        for long in keys_list:
            if long[key].startswith(short[prefix_key]):
                result = merge_two_dicts(long, short)
                combined_list.append(result)

    return combined_list


print(combine_list(rds_list, 'rds_name', cloudwatch_list, 'alarm_name'))

答案 2 :(得分:2)

from pprint import pprint

pprint([dict(y.items() + next(x.items() for x in rds_detail if x['rds_name'] in y['alarm_name'])) for y in cloudwatch_detail])

会给出

[{'alarm_name': u'emsclassicldap_db_connections', 
  'alarm_threshold': 380.0,
  'rds_name': u'emsclassicldap',
  'rds_type': u'db.m3.medium'},
 {'alarm_name': u'fra01-devops-KPX_db_connection',
  'alarm_threshold': 266.0,
  'rds_name': u'fra01-devops-KPX',
  'rds_type': u'db.t2.medium'},
 {'alarm_name': u'prodreplica_db_connections',
  'alarm_threshold': 266.0,
  'rds_name': u'prodreplica',
  'rds_type': u'db.t2.medium'}]

输出是否正确?

如果你知道两个列表中元素的顺序,你也可以这样做

pprint([dict(x.items() + y.items()) for x, y in zip(rds_detail, cloudwatch_detail)])

答案 3 :(得分:0)

您可以使用startswith检查一个字符串是否以另一个字符串开头:

from copy import deepcopy
result = []
for rds in rds_detail:
    temp = deepcopy(rds)
    for cw in cloudwatch_detail:
        # replace the condition with rds['rds_name'] in cw['alarm_name'] if the condition 
        # is substring
        if cw['alarm_name'].startswith(rds['rds_name']):
            temp.update(cw)
    result.append(temp)

result
#[{'alarm_name': 'emsclassicldap_db_connections',
#  'alarm_threshold': 380.0,
#  'rds_name': 'emsclassicldap',
#  'rds_type': 'db.m3.medium'},
# {'alarm_name': 'fra01-devops-KPX_db_connection',
#  'alarm_threshold': 266.0,
#  'rds_name': 'fra01-devops-KPX',
#  'rds_type': 'db.t2.medium'},
# {'alarm_name': 'prodreplica_db_connections',
#  'alarm_threshold': 266.0,
#  'rds_name': 'prodreplica',
#  'rds_type': 'db.t2.medium'}]