2015-04-27 3 views
1

У меня есть следующая массив-карта, созданная в Clojure.Как добавить новый узел в диаграмму Hash-Map в Clojure?

{:node 7, :children [{:node 8, :children []} {:node 6, :children []} {:node 23, :children {}} {:node 43, :children []}]} 

Как я идти о добавлении элементов в этом, работает следующий код

(def tree (assoc-in tree [:node] 12)) 

дает мне

{:node 12, :children [{:node 8, :children []} {:node 6, :children []} {:node 10, :children {}} {:node 13, :children []} {:node 28, :children []}]}` 

и работает

(def tree (assoc-in tree [:node :children] 12)) 

дает мне следующее сообщение об ошибке. Как добавить элементы в секции детей на массив-карте

Exception in thread "main" java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.Associative, 
+0

(DEF дерево (ассоциативный в дереве [{: узел: дети}] 12)) –

+0

, который дает мне '{{: node: children} 12,: node 7,: children [{: node 8,: children {}} {: node 6,: children {}} {: node 23,: children {}} {: node 43,: children {}}]} ' – Conor

+0

Вы пытаетесь обновить дочерние элементы для узла 12? –

ответ

1

Зададим наше дерево t:

(def t {:node 7, 
     :children [{:node 8, :children []} 
        {:node 6, :children []} 
        {:node 23, :children []} 
        {:node 43, :children []}]}) 

Для добавления нового ребенка к сведению:

(defn add-child [tree node] 
    (assoc-in tree 
      [:children] 
      (conj (:children tree) node))) 

(add-child t :foo) 
;; => {:node 7, 
;;  :children [{:node 8, :children []} 
;;    {:node 6, :children []} 
;;    {:node 23, :children []} 
;;    {:node 43, :children []} 
;;    :foo]} 

Из Конечно, это не совсем то, что мы хотим.

(defn make-node [value children] 
    (let [c (into [] children)] 
    {:node value 
    :children c})) 

(make-node 5 nil) 
;; => {:node 5, :children []} 

(make-node 5 [(make-node 3 nil) (make-node 7 nil)]) 
;; => {:node 5, 
;;  :children [{:node 3, :children []} 
;;    {:node 7, :children []}]} 

Строительные деревья теперь вопрос объединения make-node & add-child.

Если вы хотите работать с глубокими иерархиями, я предлагаю использовать zipper.

0

для добавления нового узла основная идея является общей. во всяком случае, прог должен знать, где разместить нового ребенка. при достижении родительского узла нового дочернего элемента prog добавляет к нему новый дочерний элемент. остальная проблема заключается в том, как пересечь граф в clojure. clojure.walk модуль предназначен для этой цели.

одна реализация добавления нового узла в графе выглядит следующим образом:

(defn tree-add 
    [root parent-key new-node] 
    (clojure.walk/postwalk #(if (= parent-key (:node %)) 
          (assoc % :children (conj (:children %) new-node)) 
          %) 
         root)) 

тестирования:

user> a 
{:node 7, :children [{:node 8, :children []}]} 
user> (tree-add a 7 {:node 99 :children []}) 
{:node 7, :children [{:node 8, :children []} {:node 99, :children []}]} 
user> (tree-add a 8 {:node 199 :children []}) 
{:node 7, :children [{:node 8, :children [{:node 199, :children []}]}]} 
Смежные вопросы