如何在 Clojure 中向哈希映射图添加新节点?
How to Add a New Node to Hash-Map Graph in Clojure?
我在 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))
给我以下错误消息。我如何将元素添加到 array-map
的子部分中
Exception in thread "main" java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.Associative,
让我们将树分配给 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。
添加新节点,基本思路是通用的。无论如何,程序需要知道在哪里放置新的 child。当到达新 child 的 parent 节点时,prog 将新 child 附加到它。剩下的问题是如何在 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 []}]}]}
我在 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))
给我以下错误消息。我如何将元素添加到 array-map
的子部分中Exception in thread "main" java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.Associative,
让我们将树分配给 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。
添加新节点,基本思路是通用的。无论如何,程序需要知道在哪里放置新的 child。当到达新 child 的 parent 节点时,prog 将新 child 附加到它。剩下的问题是如何在 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 []}]}]}