Here's a small solution that uses understanding of consistency. Hopefully it will be readable, but it definitely wonβt win any performance awards as it will re-filter the list at each recursion level. I suppose that an incredibly effective solution based on reduction is possible, but I still get the opportunity to write them - I hope someone else will publish one :).
Note. I returned the entire map for each node, since I was not sure exactly how you wanted your tree to look ...
(defn make-tree ([coll] (let [root (first (remove :parent coll))] {:node root :children (make-tree root coll)})) ([root coll] (for [x coll :when (= (:parent x) (:id root))] {:node x :children (make-tree x coll)}))) (pprint (make-tree coll)) {:node {:id 1}, :children ({:node {:parent 1, :id 2}, :children ({:node {:parent 2, :id 4}, :children ({:node {:parent 4, :id 5}, :children ({:node {:parent 5, :id 6}, :children ()} {:node {:parent 5, :id 7}, :children ({:node {:parent 7, :id 9}, :children ()})} {:node {:parent 5, :id 8}, :children ()})})})} {:node {:parent 1, :id 3}, :children ()})}
source share