如何合并含重复项的字典列表,生成目标嵌套字典结构?
你遇到的核心问题是原代码会重复生成相同的分组条目——因为外层循环遍历原列表的每一项时,都会无条件添加新条目,哪怕这个group_name+interface的组合已经处理过了。下面给你两种完全匹配需求的正确实现方式:
第一种合并形式:按group_name+interface聚合unit_names
我们可以用一个临时字典来跟踪已经处理过的组合,避免重复添加:
def merge_to_first_format(config): merged_map = {} for item in config: # 用(group_name, interface)作为唯一键,确保不会重复 key = (item['group_name'], item['interface']) if key not in merged_map: merged_map[key] = { 'group_name': item['group_name'], 'interface': item['interface'], 'unit_names': [] } merged_map[key]['unit_names'].append(item['unit_name']) # 把字典的值转成列表,就是最终结果 return list(merged_map.values()) # 测试示例 original_config = [ { "group_name": "CUSTOMER_RED", "interface": "ae4", "unit_name": 2520 }, { "group_name": "CUSTOMER_RED", "interface": "ae4", "unit_name": 4091 }, { "group_name": "CUSTOMER_BLUE", "interface": "ae4", "unit_name": 847 }, { "group_name": "CUSTOMER_BLUE", "interface": "ae4", "unit_name": 103 } ] print(merge_to_first_format(original_config))
运行后会输出你想要的第一种结构:
[
{ "group_name": "CUSTOMER_RED", "interface": "ae4", "unit_names": [2520, 4091] },
{ "group_name": "CUSTOMER_BLUE", "interface": "ae4", "unit_names": [847, 103] }
]
第二种合并形式:按group_name聚合嵌套的interfaces
如果要实现嵌套层级的结构,我们可以调整临时字典的层级,先按group_name分组,再在每个分组下管理对应的接口和单元列表:
def merge_to_second_format(config): merged_map = {} for item in config: group_name = item['group_name'] interface = item['interface'] # 先处理分组层级 if group_name not in merged_map: merged_map[group_name] = { 'group_name': group_name, 'interfaces': {} } # 再处理接口层级 if interface not in merged_map[group_name]['interfaces']: merged_map[group_name]['interfaces'][interface] = { 'unit_names': [] } merged_map[group_name]['interfaces'][interface]['unit_names'].append(item['unit_name']) return list(merged_map.values()) # 测试示例 print(merge_to_second_format(original_config))
这个函数会输出你需要的第二种结构:
[
{ "group_name": "CUSTOMER_RED", "interfaces": {"ae4": {"unit_names": [2520, 4091]}} },
{ "group_name": "CUSTOMER_BLUE", "interfaces": {"ae4": {"unit_names": [847, 103]}} }
]
原代码问题复盘
你的原代码之所以产生重复结果,是因为外层循环遍历原列表的每一项时,都会生成一个新条目并添加到return_config中——哪怕当前的group_name和interface已经被处理过一次。而上面的两种方法都是先用字典做去重跟踪,最后再把字典的值转为列表,从根源上避免了重复条目。
内容的提问来源于stack exchange,提问作者tread

