Имеется список словарей, таких как:
history = [
{
"actions": [{"action": "baz", "people": ["a"]}, {"action": "qux", "people": ["d", "e"]}],
"events": ["foo"]
},
{
"actions": [{"action": "baz", "people": ["a", "b", "c"]}],
"events": ["foo", "bar"]
},
]
Какой самый эффективный (пока еще читаемый) способ получить список диктов, где каждый диктователь является уникальным event
и списокдействия для этого события были объединены на основе клавиши action
. Например, для приведенного выше списка желаемый вывод:
output = [
{
"event": "foo",
"actions": [
{"action": "baz", "people": ["a", "b", "c"]},
{"action": "qux", "people": ["d", "e"]}
]
},
{
"event": "bar",
"actions": [
{"action": "baz", "people": ["a", "b", "c"]}
]
},
]
Я не могу изменить структуру вывода, так как он потребляется чем-то внешним. Я написал следующий код, который работает, но очень многословен и плохо читается.
from collections import defaultdict
def transform(history):
d = defaultdict(list)
for item in history:
for event in item["events"]:
d[event] = d[event] + item["actions"]
transformed = []
for event, actions in d.items():
merged_actions = {}
for action in actions:
name = action["action"]
if merged_actions.get(name):
merged_actions[name]["people"] = list(set(action["people"]) | set(merged_actions[name]["people"]))
else:
merged_actions[name] = {
"action": action["action"],
"people": action["people"]
}
transformed.append({
"event": event,
"actions": list(merged_actions.values())
})
return transformed
Я нацеливаюсь только на python3.6 +