最简单的方法是通过在每一步执行完整扫描来递归构建它:
(defn tree
([flat-nodes]
(tree flat-nodes 0))
([flat-nodes parent-id]
(for [node flat-nodes
:when (= (:parent node) parent-id)]
(assoc node
:nodes (tree flat-nodes (:id node))))))
and then
=> (tree data)
({:parent 0, :name "a", :nodes
({:parent 1, :name "a_1", :nodes
({:parent 4, :name "a_1_1", :nodes (), :id 7}), :id 4}
{:parent 1, :name "a_2", :nodes (), :id 5}), :id 1}
{:parent 0, :name "b", :nodes
({:parent 2, :name "b_1", :nodes (), :id 6}), :id 2}
{:parent 0, :name "c", :nodes (), :id 3})
更新:更有效的变体
(defn tree [flat-nodes]
(let [children (group-by :parent flat-nodes)
nodes (fn nodes [parent-id]
(map #(assoc % :nodes (nodes (:id %)))
(children parent-id)))]
(nodes 0)))