how to transform a seq into a tree

拜拜、爱过 提交于 2019-12-22 05:25:30

问题


I have a seq of maps such as the coll below. I want to arrange it in a tree. Each map has a key named :parent which is the :id of the parent. Any hints on how can I do it ?

(def coll [{:id 1} 
          {:id 2 :parent 1} 
          {:id 3 :parent 1}
          {:id 4 :parent 2}
          {:id 5 :parent 4}
          {:id 6 :parent 5}
          {:id 7 :parent 5}
          {:id 8 :parent 5}
          {:id 9 :parent 7}])

回答1:


If it walks like a tree...

(require '[clojure.zip :as z])

(defn create-zipper [s]
  (let [g (group-by :parent s)] 
    (z/zipper g #(map :id (g %)) nil (-> nil g first :id))))

(def t (create-zipper coll)) ; using the coll defined in the OP

(-> t z/root)
;=> 1

(-> t z/children)
;=> (2 3)

(-> t z/next z/children)
;=> (4)

Note that you may preserve the format of the original nodes (rather than just returning id numbers) by using #(g (% :id)) as the children and (first (g nil)) as the root.

You can use post-order traversal to build up another representation of the tree if desired.




回答2:


Here's a little solution that uses a sequence comprehension. Hopefully it's readable, but it definitely won't win any awards for performance as it re-filters the list at every level of recursion. I imagine there's an amazingly efficient reduce-based solution possible, but I'm still getting the hang of writing those - hopefully someone else will post one :).

Note - I've returned the whole map for each node, as I wasn't sure exactly what you wanted your tree to look like...

(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 ()})}


来源:https://stackoverflow.com/questions/18779718/how-to-transform-a-seq-into-a-tree

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!