我有一个形式的字典:
[
{
"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
}
}
如何合并它以形成一个列表,如:
[
{
"group_name": "CUSTOMER_RED",
"interface": "ae4",
"unit_names": [2520, 4091]
},
{
"group_name": "CUSTOMER_BLUE",
"interface": "ae4",
"unit_names": [847, 103]
},
}
或者更简单:
[
{
"group_name": "CUSTOMER_RED",
"interfaces": ["ae4": "unit_names": [2520, 4091]]
},
{
"group_name": "CUSTOMER_BLUE",
"interface": ["ae4": "unit_names": [847, 103]]
},
}
我尝试过:
def merge_relevant_config(config):
return_config = []
for item in config:
name = item['group_name']
interface = item['interface']
units = []
for item in config:
if item['group_name'] == name and item['interface'] == interface:
units.append(item['unit_name'])
return_config.append({
'name': name,
'interface': interface,
'units': units
})
return return_config
但是返回的结果却令人失望:
[
{
"name": "CUSTOMER_RED",
"interface": "ae4",
"units": [
2520,
4091
]
},
{
"name": "CUSTOMER_RED",
"interface": "ae4",
"units": [
2520,
4091
]
},
{
"name": "CUSTOMER_BLUE",
"interface": "ae4",
"units": [
847,
103
]
},
{
"name": "CUSTOMER_BLUE",
"interface": "ae4",
"units": [
847,
103
]
}
]
答案 0 :(得分:6)
这是一种方法。
例如:
data = [
{
"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
}
]
result = {}
for i in data:
if i['group_name'] not in result:
#if group by `group_name` & `interface` use --> result[(i['group_name'], i['interface'])]
result[i['group_name']] = {'group_name': i['group_name'], 'interface': i['interface'], "unit_names": [i['unit_name']]}
else:
result[i['group_name']]["unit_names"].append(i['unit_name'])
print(list(result.values()))
输出:
[
{
'group_name': 'CUSTOMER_RED',
'interface': 'ae4',
'unit_names': [2520, 4091]
},
{
'group_name': 'CUSTOMER_BLUE',
'interface': 'ae4',
'unit_names': [847, 103]
}
]
答案 1 :(得分:1)
另一个答案不考虑多个接口,此示例可以:
def merge_config(config):
merged = []
sets = {}
for item in config:
as_text = '{}-{}'.format(item['group_name'], item['interface'])
if as_text in sets.keys():
sets[as_text].append(item['unit_name'])
else:
sets[as_text] = [item['unit_name']]
for k, v in sets.items():
group_name, interface = k.split('-')
merged.append(
{
'group_name': group_name,
'interface': interface,
'unit_names': v
}
)
return merged
答案 2 :(得分:0)
这里有一个使用itertools.groupy
和自定义函数的多功能功能。您可以定义要分组的键,而无需知道内部键,您仍然可以完全合并字典:
from itertools import groupby
def merge_dicts(*dcts):
# define a merge function
merged = {}
for dct in dcts:
for k, v in dct.items():
if merged.setdefault(k, v) != v:
if not isinstance(merged.get(k), list):
merged[k] = [merged.get(k)]
merged.get(k).append(v)
return merged
group_key = 'group_name'
result = [merge_dicts(*grouped) for key, grouped in groupby(l, lambda dct: dct.get(group_key))]
输出:
[
{
'group_name': 'CUSTOMER_RED',
'interface': 'ae4',
'unit_name': [2520, 4091]
},
{
'group_name': 'CUSTOMER_BLUE',
'interface': 'ae4',
'unit_name': [847, 103]
}
]
答案 3 :(得分:0)
要完全结合所有常用键,可以将递归与itertools.groupby
一起使用:
from itertools import groupby as gb
data = [{'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}]
def group(d):
_d = [(a, list(b)) for a, b in gb(sorted(d, key=lambda x:x[0]), key=lambda x:x[0])]
return [b if not (j:=[l for i in k if (l:=i[1:])]) else {a:{b:group(j)}} for (a, b), k in _d]
print(group([list(i.items()) for i in data]))
输出:
[{'group_name': {'CUSTOMER_BLUE': [{'interface': {'ae4': [103, 847]}}]}}, {'group_name': {'CUSTOMER_RED': [{'interface': {'ae4': [2520, 4091]}}]}}]