Группировка словарей Python в иерархической форме с несколькими ключами?
Вот мой список диктовок:
[{'subtopic': 'kuku',
'topic': 'lulu',
'attachments': ['ttt'],
'text': 'abc'},
{'subtopic': 'tutu',
'topic': 'lulu',
'attachments': ['pipu'],
'text': 'bubb'},
{'subtopic': 'did',
'topic': 'lulu',
'attachments': ['ktop'],
'text': 'gfg'},
{'subtopic': 'polo',
'topic': 'lulu',
'attachments': ['vuvu'],
'text': 'prolo'},
{'subtopic': 'ssd',
'topic': 'lulu',
'attachments': ['jkjk'],
'text': 'vint'},
{'subtopic': 'plp',
'topic': 'lulu',
'attachments': ['fre'],
'text': 'viw'},
{'subtopic': 'prw',
'topic': 'kll',
'attachments': [],
'text': 'kkk'},
{'subtopic': 'prw',
'topic': 'kll',
'attachments': [],
'text': 'fgfger2'}]
Я хотел бы сгруппировать по темам и подтемам, чтобы получить окончательный результат:
{
"lulu": {
"kuku": {
'attachments': ['sample'],
'text': ['sample']
},
"pupu": {
'attachments': ['sample'],
'text': ['sample']
},
"buru": {
'attachments': ['sample1',
'sample2'],
'text': ['sample1',
'sample2']
},
"titi": {
'attachments': ['sample'],
'text': ['sample']
},
"huhu": {
'attachments': ['sample'],
'text': ['sample']
}
},
"viriri": {
"vururur": {
'attachments': [],
'text': ['sample']
}
}
}
Я использую:
groups = ['topic', 'subtopic', "text", "attachments"]
groups.reverse()
def hierachical_data(data, groups):
g = groups[-1]
g_list = []
for key, items in itertools.groupby(data, operator.itemgetter(g)):
g_list.append({key:list(items)})
groups = groups[0:-1]
if(len(groups) != 0):
for e in g_list:
for k, v in e.items():
e[k] = hierachical_data(v, groups)
return g_list
print(hierachical_data(filtered_top_facts_dicts, groups))
Но получаю ошибку для хеширования списков. Посоветуйте, пожалуйста, как преобразовать мой json в нужный формат.
2 ответа
Я думаю, что самое чистое решение - использоватьdictlib
с одной строкой:
from functools import reduce
import dictlib
reduce(
lambda x, y: dictlib.union_setadd(x, y),
[
{
x["topic"]: {
x["subtopic"]: {
list(x.keys())[2]: list(x.values())[2],
list(x.keys())[3]: [list(x.values())[3]],
}
}
}
for x in d
],
)
гдеd
ваш первоначальный список иdictlib.union_setadd()
объединяет словари, выполняя логику setadd, как с str
и int
. Обратите внимание, что при вводеreduce
, слияние является последовательным и кумулятивным для всех записей вашего списка.
Надеюсь это поможет.
Чтобы сгруппировать список словарей по темам и подтемам, вы можете создать пустой словарь, а затем пройтись по списку словарей, чтобы добавить каждый элемент на соответствующий уровень вложенности в словарь.
result = {}
for item in data:
topic = item['topic']
subtopic = item['subtopic']
if topic not in result:
result[topic] = {}
if subtopic not in result[topic]:
result[topic][subtopic] = {}
result[topic][subtopic]['attachments'] = []
result[topic][subtopic]['text'] = []
result[topic][subtopic]['attachments'].extend(item['attachments'])
result[topic][subtopic]['text'].append(item['text'])
# Reverse the order of the sub-dictionaries within each topic
for topic, subtopics in result.items():
result[topic] = dict(reversed(list(subtopics.items())))
После завершения этого цикла результирующий словарь будет в формате, который вы описали, с темой и подтемой в качестве ключей и вложениями и текстом в качестве значений в каждом подсловаре.
Выход:
{'AWS': {'GitHub': {'attachments': ['{"workflow.name": "view_pull_request","workflow.parameters": {"region": "us-west"}}'],
'text': ['Sure, I can help with GitHub pull requests']},
'S3': {'attachments': ['{"workflow.name": "aws_s3_file_copy","workflow.parameters": {"region": "us-west"}}'],
'text': ['Sure, I can help you with the process of copying on S3']},
'EC2': {'attachments': ['{"workflow.name": "aws_ec2_create_instance","workflow.parameters": {"region": "us-east"}}',
'{"workflow.name": "aws_ec2_security_group_info","workflow.parameters": {"region": "us-east"}}'],
'text': ['Sure, I can help creating an EC2 machine',
'Sure, I can help with various information about AWS security groups']},
'ECS': {'attachments': ['{"workflow.name": "aws_ecs_restart_service","workflow.parameters": {"region": "us-east"}}'],
'text': ['Sure! I can help with restarting AWS ECS Service']},
'IAM': {'attachments': ['{"workflow.name": "aws_iam_policies_info","workflow.parameters": {"region": "us-east"}}'],
'text': ['Sure! I can help with AWS IAM policies info']}},
'Topic Title': {'Subtopic Title': {'attachments': [],
'text': ['This is another fact', 'This is a fact']}}}