Unknown
Unknown

Reputation: 1397

Convert vector of maps to a tree

I need to convert a vector of maps like this:

[{:id 1 :parent nil :name "a"}
 {:id 2 :parent 1 :name "b"}
 {:id 3 :parent 2 :name "c"}
 {:id 4 :parent 2 :name "d"}
 {:id 5 :parent 4 :name "e"}]

to this:

[{:id 1 
  :parent nil 
  :name "a" 
  :nodes [{:id 2 
           :parent 1 
           :name "b" 
           :nodes [{:id 3 
                    :parent 2 
                    :name "c"}
                   {:id 4 
                    :parent 2 
                    :name "d" 
                    :nodes [{:id 5 :parent 4 :name "e"}]}]}]}]

UPDATE:

As per requested so far I have this:

(defn enum [s]
  (map vector (range) s))

(defn build-tree [tree current-path current-parent gr]
      (if-let [nodes (gr current-parent)]
        (let [current-path (conj current-path :nodes)
              new-tree (assoc-in tree current-path nodes)]
          (first 
           (for [[i node] (enum (get-in new-tree current-path))]
             (build-tree new-tree (conj current-path i) (:id node) gr))))
        tree))

(defn list->tree [ls]
  (let [gr (group-by :parent ls)
        root (first (gr nil))]
    (build-tree root [] (:id root) gr)))

However I really doubt this is idiomatic + it is not working anyway (creates only first nodes, the rest are ignored). I also doubt that creating a tree is so hard. I really think that I am missing something.

Upvotes: 0

Views: 201

Answers (1)

Symfrog
Symfrog

Reputation: 3418

You can either use an adjacency list or a recursive approach.

Both approaches are discussed in more detail as answers to this very similar question.

Upvotes: 1

Related Questions