7

以下の coll のような一連のマップがあります。ツリーに並べたい。各マップには、親の :id である :parent という名前のキーがあります。どうすればそれを行うことができますか?

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

2 に答える 2

7

木のように歩けば…

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

#(g (% :id))子および(first (g nil))ルートとして使用することで、(ID 番号を返すだけでなく) 元のノードの形式を保持できることに注意してください。

必要に応じて、ポストオーダー トラバーサルを使用してツリーの別の表現を構築できます。

于 2013-09-13T17:33:11.197 に答える
2

これは、シーケンス内包表記を使用する小さなソリューションです。読みやすいことを願っていますが、再帰のすべてのレベルでリストを再フィルタリングするため、パフォーマンスの賞を獲得することは間違いありません. 驚くほど効率的なリデュースベースのソリューションが可能だと思いますが、まだそれらを書くコツをつかんでいます-他の誰かが投稿してくれることを願っています:)。

注 - ツリーをどのように見せたいか正確にわからなかったため、各ノードのマップ全体を返しました...

(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 ()})}
于 2013-09-13T10:09:18.867 に答える