#python #recursion
#python #рекурсия
Вопрос:
Пример dict :
simple_dict = {
'root 1': [
'root 1 1',
'root 1 2'
],
'root 2': [
'root 2 1',
'root 2 2',
{'root 2 3': [
'root 2 3 1',
'root 2 3 2'
]},
'root 2 4',
],
'root 3': ['root 3 1']
}
Я пытаюсь преобразовать его в это :
root_dict = [
{
'name': 'root1',
'children': [
{
'name': 'root 1 1'
},
{
'name': 'root 1 2'
}
]
},
{
'name': 'root 2',
'children': [
{
'name': 'root 2 1'
},
{
'name': 'root 2 2'
},
{
'name': 'root 2 3',
'children': [
{
'name': 'root 2 3 1'
},
{
'name': 'root 2 3 2'
}
]
},
{
'name': 'root 2 4'
}
]
},
{
'name': 'root 3',
'children': [
{
'name': 'root 3 1'
}
]
}
]
все, что я получил, это написал функцию, которая рекурсивно пересекает словарь, но теряет третий уровень вложенности:
def dict_to_tree_options(tree):
options = []
for key, value in tree.items():
elem = {
'name': f'{key}',
'children': []
}
#print(key, value)
for i in value:
if isinstance(i, dict):
#print('deeper')
outer_elem = {
'name': f'{i}'
}
dict_to_tree_options(i)
else:
inner_elem = {
'name': f'{i}'
}
elem['children'].append(inner_elem)
#print(key, i, 'n')
options.append(elem)
print(options)
[{'name': 'root 2 3', 'children': [{'name': 'root 2 3 1'}, {'name': 'root 2 3 2'}]}]
[{'name': 'root 1', 'children': [{'name': 'root 1 1'}, {'name': 'root 1 2'}]}, {'name': 'root 2', 'children': [{'name': 'root 2 1'}, {'name': 'root 2 2'}, {'name': 'root 2 4'}]}, {'name': 'root 3', 'children': [{'name': 'root 3 1'}]}]
по-видимому, я не понимаю, как должна работать рекурсивная функция, потому что мне кажется, что каждый раз, когда вызывается рекурсия, переменная options переопределяется, и я не понимаю, что с ней происходит дальше
Комментарии:
1. Вторая структура выглядит еще большей мерзостью, чем первая. Какова здесь цель? И да, поскольку ваша первая строка —
options = []
это то, что она будет воссоздаваться при каждом вызове. Вы хотели передать это?2. Мне нужно преобразовать первый словарь в формат второго, потому что система, которую я использую, принимает его только в этой форме. Посмотрите на вторую строку вывода, это почти то, что мне нужно, но это освобождает 3-й рычаг root, пожалуйста, помогите мне, мне это нужно
Ответ №1:
Вот реализация, которая выполняет то, что вы просили:
def transform(value):
if not isinstance(value, (dict, list)):
return {'name': value}
if isinstance(value, list):
return [transform(item) for item in value]
return [{'name': key, 'children': transform(value_)} for key, value_ in value.items()]
Комментарии:
1. Почти работает, но есть небольшая проблема:
[{'name': 'root 2 3', 'children': [{'name': 'root 2 3 1'}, {'name': 'root 2 3 2'}]}]
эта часть заключена в список, но не должна быть2. Код приводит к желаемому результату, который вы хотели, вы не можете сохранить его только как dict, поскольку
name
in не уникален….
Ответ №2:
Вот способ сделать это. При выполнении рекурсивной функции всегда сначала думайте о своих условиях остановки!
def format_dict(entry):
if not isinstance(entry, (list, dict)):
return {'name': entry}
if isinstance(entry, list):
return [format_dict(e) for e in entry]
if isinstance(entry, dict):
children = [{
'name': key, 'children': format_dict(value)
} for key, value in entry.items()]
if len(children) == 1:
return children[0]
return children
Комментарии:
1. Спасибо за прекрасное рабочее решение, но я получил
None
, если значение содержит целое число, можете ли вы это исправить, пожалуйста?2. Готово, просто замените
if isinstance(entry, str)
наif not isinstance(entry, (list, dict))
3. Да, это так, я только что добавил
return {'name': str(entry)}
, большое вам спасибо! :3
Ответ №3:
Вы могли бы попытаться вернуть массив параметров. Затем, когда элемент является dict, вы должны добавить {name: f'{I}’, дочерние элементы: dict_to_tree_options(I)} к дочерним элементам.
Ответ №4:
Вы можете использовать рекурсию с пониманием списка:
def to_tree(d):
if not isinstance(d, dict):
return {'name':d}
return [{'name':a, 'children':list(map(to_tree, b))} for a, b in d.items()]
import json
simple_dict = {'root 1': ['root 1 1', 'root 1 2'], 'root 2': ['root 2 1', 'root 2 2', {'root 2 3': ['root 2 3 1', 'root 2 3 2']}, 'root 2 4'], 'root 3': ['root 3 1']}
print(json.dumps(to_tree(simple_dict), indent=4))
Вывод:
[
{
"name": "root 1",
"children": [
{
"name": "root 1 1"
},
{
"name": "root 1 2"
}
]
},
{
"name": "root 2",
"children": [
{
"name": "root 2 1"
},
{
"name": "root 2 2"
},
[
{
"name": "root 2 3",
"children": [
{
"name": "root 2 3 1"
},
{
"name": "root 2 3 2"
}
]
}
],
{
"name": "root 2 4"
}
]
},
{
"name": "root 3",
"children": [
{
"name": "root 3 1"
}
]
}
]