遍历一个列表并将数据添加到Python中字典的另一个嵌套列表中

时间:2020-05-04 20:26:45

标签: python python-3.x list

我在这里遇到问题:

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

做到这一点的最佳方法是什么?非常感谢!

3 个答案:

答案 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()
]

Sample code