【问题标题】:How to Add a New Node to Hash-Map Graph in Clojure?如何在 Clojure 中向 Hash-Map 图中添加新节点?
【发布时间】:2015-04-27 14:29:22
【问题描述】:

我在 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,

【问题讨论】:

  • (def tree (asoc-in tree [{:node :children}] 12))
  • 跑步给了我{{:node :children} 12, :node 7, :children [{:node 8, :children {}} {:node 6, :children {}} {:node 23, :children {}} {:node 43, :children {}}]}
  • 您是否尝试更新节点 12 的子节点?
  • 我实际上试图以{:node 8, :children {}} 的格式将一个新的孩子插入到 :node 7 的孩子中,但是我无法让它工作,所以我尝试只插入一个数字一直
  • 生成的树是什么样的?

标签: vector clojure array-map


【解决方案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-nodeadd-child 结合起来即可。

如果您想处理较深的层次结构,我建议使用zipper

【讨论】:

    【解决方案2】:

    对于添加一个新节点,基本思路是通用的。无论如何,编程序需要知道将新孩子放在哪里。当到达新子节点的父节点时,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 []}]}]}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-23
      • 1970-01-01
      • 2022-12-05
      • 1970-01-01
      • 2014-11-20
      • 2014-11-11
      • 2017-10-06
      • 2018-01-28
      相关资源
      最近更新 更多