Я совершенно новичок в функциональном программировании и эликсире, и даже после изучения синтаксиса, мне трудно сосредоточиться на решении проблем с неизменяемостью.
Рассмотрим следующий простой алгоритм, который я написал на python. Получает список уровней дерева. Каждый уровень представляет собой список узлов, где узел содержит идентификатор, (изначально) пустой список детей и указатель на его родительский узел. Это упорядочивает дерево так, что у каждого родителя есть его дети в его списке детей, и возвращает корень (и). Например, следующий вход:
[[{"id": 10,
"children": [],
"parent_id": null}],
[{"id": 12,
"children": [],
"parent_id": 10},
{"id": 18,
"children": [],
"parent_id": 10},
{"id": 13,
"children": [],
"parent_id": 10}],
[{"id": 17,
"children": [],
"parent_id": 12},
{"id": 16,
"children": [],
"parent_id": 13},
{"id": 15,
"children": [],
"parent_id": 12}]}]
Будет преобразовано в следующий вывод:
[{"id": 10,
"children":
[{"id": 12,
"children":
[{"id": 17,
"children": [],
"parent_id": 12},
{"id": 15,
"children": [],
"parent_id": 12}],
"parent_id": 10},
{"id": 18,
"children": [],
"parent_id": 10},
{"id": 13,
"children":
[{"id": 16,
"children": [],
"parent_id": 13}],
"parent_id": 10}],
"parent_id": null}]
Код:
def build_tree(levels):
ids_to_nodes = []
for i in range(len(levels)):
level = levels[i]
ids_to_nodes.append({})
for node in level:
ids_to_nodes[i][node["id"]] = node
if i > 0:
for node in level:
levels[i - 1][node["parent_id"]]["children"].append(node)
return levels[0].values()
Самое близкое, что мне удалось реализовать в эликсире, это
def fix_level(levels, ids_to_nodes, i) do
if i < length(levels) do
level = Enum.at(levels, i)
new_level =
Enum.reduce level, %{}, fn node, acc ->
Map.put(acc, node["id"], node)
end
ids_to_nodes = ids_to_nodes ++ [new_level]
if i > 0 do
Enum.reduce level, Enum.at(ids_to_nodes, i - 1)[node["parent_id"]], fn node, acc ->
Map.put(acc, "children", Enum.at(ids_to_nodes, i - 1)[node["parent_id"]]["children"] ++ [node]) # Doesn't work coz creates new map
end
end
fix_level(params, ids_to_nodes, i + 1)
end
Map.values(ids_to_nodes[0])
end
def fix(levels) do
fix_level(levels, ids_to_nodes, 0)
end
Я знаю, что код очень неэффективен во многих местах, особенно вокруг концов списков, - но я не уверен, как эффективно переписать их, и, что более важно, я полностью заблокирован в отмеченная линия. Я думаю, что слишком много думаю об императиве / объектно-ориентированном подходе. Помощь в понимании функционального программирования будет оценена.