Перебрать список и добавить данные в другой вложенный список словаря в Python - PullRequest
1 голос
/ 04 мая 2020

У меня проблема:

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 ]

2 голосов
/ 04 мая 2020

Уже есть несколько хороших ответов, я добавляю один, используя 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 голосов
/ 04 мая 2020
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 голос
/ 04 мая 2020

Если ваша цель - обновить 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()
]

Пример кода

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...