【发布时间】:2019-01-23 03:14:54
【问题描述】:
我对函数式编程和长生不老药完全陌生,即使在学习了语法之后,我也很难集中精力解决不变性问题。
考虑以下我用 python 编写的简单算法。它接收树的级别列表。每个级别都是一个节点列表,其中一个节点包含一个 id、一个(最初)为空的子节点列表和指向其父节点的指针。它对树进行排序,使得每个父母在他的孩子列表中都有他的孩子并返回根。例如,以下输入:
[[{"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()
我在 elixir 中最接近实现这一点的是
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
我知道代码在很多地方都非常低效,尤其是在列表的末尾 - 但我不确定如何以有效的方式重写它们,更重要的是,我完全被阻止了标记的线。我认为我以命令式/面向对象的方式思考太多了。帮助理解函数式编程将不胜感激。
【问题讨论】:
-
您能否提供示例性输入和所需的输出?
-
在编辑中提供。谢谢