我在这里遇到问题:
orgn_data = [{ "host1" : [{'port': 8080, 'name': 'data1'}, {'port': 8000, 'name': 'data2'}, {'port': 80, 'name': 'data3'}]},
{"host2": [{'port': 443, 'name': 'data1'}, {'port': 8000, 'name': 'data2'}]}
]
res_data = [{'host1': ['1', '0', '1']}, {'host2': ['1', '0']}]
基本上,res_data是与orgn_data列表具有相同主机的结果列表。我想将相同主机的res_data以相同顺序合并到orgn列表中。
我可以保证res_data的顺序与orgn_data本身的顺序相同。但是,外部列表可能并不总是与其始终相同(可以是多个主机)。因此,这意味着必须首先查找主机名才能获得正确的对。
最终结果应如下所示:
final_data = [{ "host1" : [{'port': 8080, 'name': 'data1', "status": 1}, {'port': 8000, 'name': 'data2', "status": 0}, {'port': 80, 'name': 'data3', "status": 1}]},
{"host2": [{'port': 443, 'name': 'data1', "status": 1}, {'port': 8000, 'name': 'data2', "status": 0}]}
]
做到这一点的最佳方法是什么?非常感谢!
答案 0 :(得分:2)
import copy
final_data = copy.deepcopy(orgn_data)
aux_dict = { host:lst for d in res_data for host, lst in d.items() }
# aux_dict == {'host1': ['1', '0', '1'], 'host2': ['1', '0']}
for dct in final_data:
# dct == { "host1" : [{'port': 8080, 'name': 'data1'}, {'port': 8000, 'name': 'data2'}, {'port': 80, 'name': 'data3'}]} etc.
for host, lst in dct.items():
# host == "host1" --> lst == [{'port': 8080, 'name': 'data1'}, {'port': 8000, 'name': 'data2'}, {'port': 80, 'name': 'data3'}]
for i, subdct in enumerate(lst):
# i == 0 --> subdct == {'port': 8080, 'name': 'data1'}
subdct['status'] = aux_dict[host][i]
答案 1 :(得分:2)
已经有一些不错的答案,我使用itertools.groupby
添加了一个答案:
from itertools import groupby
for k, (orgn, res) in groupby(sorted(orgn_data + res_data, key=lambda k: [*k.keys()][0]), lambda k: [*k.keys()][0]):
for v, s in zip(orgn[k], res[k]):
v['status'] = s
print(orgn_data)
打印:
[{'host1': [{'port': 8080, 'name': 'data1', 'status': '1'}, {'port': 8000, 'name': 'data2', 'status': '0'}, {'port': 80, 'name': 'data3', 'status': '1'}]},
{'host2': [{'port': 443, 'name': 'data1', 'status': '1'}, {'port': 8000, 'name': 'data2', 'status': '0'}]}]
答案 2 :(得分:1)
如果您的目标是更新orgn_data
使其包含status
键:
order = lambda x: next(iter(x.keys()))
for org, res in zip(*map(lambda lst: sorted(lst, key=order), (orgn_data, res_data))):
for key, lst in org.items():
for i, inner in enumerate(lst):
inner['status'] = res[key][i]
结果:
[{'host1': [{'name': 'data1', 'port': 8080, 'status': '1'},
{'name': 'data2', 'port': 8000, 'status': '0'},
{'name': 'data3', 'port': 80, 'status': '1'}]},
{'host2': [{'name': 'data1', 'port': 443, 'status': '1'},
{'name': 'data2', 'port': 8000, 'status': '0'}]}]
如果您想要数据的副本,则另一个答案可以使您更好地覆盖。 但是,如果您喜欢冒险和疯狂,可以尝试以下方法:
order = lambda x: next(iter(x.keys()))
final_data = [
{key: [
{k: v for k, v in list(inner.items()) + [('status', res[key][i])]}
for i, inner in enumerate(lst)
]
}
for org, res in zip(*map(lambda lst: sorted(lst, key=order), (orgn_data, res_data)))
for key, lst in org.items()
]