Clojure разбирает вложенные векторы - PullRequest
0 голосов
/ 19 ноября 2018

Я хочу преобразовать структуру дерева clojure в карту с ее зависимостями

Например, такой ввод:

[{:value "A"} 
  [{:value "B"} 
    [{:value "C"} {:value "D"}] 
  [{:value "E"} [{:value "F"}]]]]

эквивалентно:

:A
  :B
    :C
    :D
  :E
    :F

вывод:

 {:A [:B :E] :B [:C :D] :C [] :D [] :E [:F] :F}

Я взглянул на tree-seq и молнии, но не могу понять!

Ответы [ 2 ]

0 голосов
/ 19 ноября 2018

Вот способ создать нужную карту, используя молнию для прохождения дерева.Сначала давайте упростим дерево ввода, чтобы оно соответствовало вашему выходному формату (карты :value строки → ключевые слова):

(def tree
  [{:value "A"}
   [{:value "B"} [{:value "C"} {:value "D"}]
    {:value "E"} [{:value "F"}]]])

(def simpler-tree
  (clojure.walk/postwalk
   #(if (map? %) (keyword (:value %)) %)
   tree))
;; [:A [:B [:C :D] :E [:F]]]

Затем вы можете пройти по дереву с помощью loop / recur и clojure.zip/next,используя две привязки loop: текущую позицию в дереве и строящуюся карту.

(loop [loc (z/vector-zip simpler-tree)
       deps {}]
  (if (z/end? loc)
    deps ;; return map when end is reached
    (recur
     (z/next loc) ;; advance through tree
     (if (z/branch? loc)
       ;; for (non-root) branches, add top-level key with direct descendants
       (if-let [parent (some-> (z/prev loc) z/node)]
         (assoc deps parent (filterv keyword? (z/children loc)))
         deps)
       ;; otherwise add top-level key with no direct descendants
       (assoc deps (z/node loc) [])))))
=> {:A [:B :E], :B [:C :D], :C [], :D [], :E [:F], :F []}
0 голосов
/ 19 ноября 2018

Это легко сделать с помощью библиотеки tupelo.forest. Я переформатировал исходные данные, чтобы они соответствовали синтаксису Hiccup:

(dotest
  (let [relationhip-data-hiccup [:A
                                 [:B
                                  [:C]
                                  [:D]]
                                 [:E
                                  [:F]]]
        expected-result         {:A [:B :E]
                                 :B [:C :D]
                                 :C []
                                 :D []
                                 :E [:F]
                                 :F []} ]
    (with-debug-hid
      (with-forest (new-forest)
        (let [root-hid (tf/add-tree-hiccup relationhip-data-hiccup)
              result   (apply glue (sorted-map)
                         (forv [hid (all-hids)]
                           (let [parent-tag (grab :tag (hid->node hid))
                                 kid-tags   (forv [kid-hid (hid->kids hid)]
                                              (let [kid-tag (grab :tag (hid->node kid-hid))]
                                                kid-tag))]
                             {parent-tag kid-tags})))]
          (is= (format-paths (find-paths root-hid [:A]))
            [[{:tag :A}
              [{:tag :B} [{:tag :C}] [{:tag :D}]]
              [{:tag :E} [{:tag :F}]]]])
          (is= result  expected-result ))))))

API документы здесь . Проект README (в процессе) находится здесь . Видео с Clojure Conj 2017 находится здесь .

Вы можете увидеть приведенный выше живой код в репозитории проекта .

...