将具有默认值的键添加到嵌套的clojure hashmap

时间:2018-01-11 22:33:45

标签: recursion clojure hashmap clojurescript

我尝试做Clojure但坚持使用嵌套的hashmap。 我有这样的结构:

{:type "view" 
 children: [
     {:type "view" 
      :id "123"} 
     {:type "view" 
      :children [
         {:type "view"}]}]}

现在我想用随机字符串向每个hashmap添加字段:id(如果不存在)。得到这样的东西:

{:type "view" 
 :id "43434"
 children: [
     {:type "view" 
      :id "123"} 
     {:type "view" 
      :id "456"
      :children [
         {:type "view"
          :id "5656"}]}]}

2 个答案:

答案 0 :(得分:8)

您可以使用clojure.walk/postwalk执行此操作:

 (walk/postwalk
  (fn [v]
    (if (and (map? v) (nil? (:id v)))
      (assoc v :id (str (rand-int 9999)))
      v))
   data)
=>
{:type "view"
 :id "3086"
 :children [{:type "view"
             :id "123"}
            {:type "view"
             :id "8243"
             :children [{:type "view" :id "3222"}]}]}

...其中data是您的输入地图。 postwalk遍历您的嵌套地图,assoc在每张没有地图的地图上添加:id键(随机整数字符串)。

答案 1 :(得分:0)

除了walk变体之外还有更多:

最简单的解决方案是递归更新

(defn upd [{:keys [id children] :as data}]
  (assoc data
         :id (if id
               id
               (str (rand-int Integer/MAX_VALUE)))
         :children (mapv upd children)))
#'user/upd

user> (upd data)
;;=> {:type "view", 
;;    :children [{:type "view", :id "123", :children []} 
;;               {:type "view", 
;;                :children [{:type "view", :id "35223257", 
;;                            :children []}], 
;;                :id "551012526"}], 
;;    :id "1899442274"}

你也可以使用clojure的拉链:

(require '[clojure.zip :as z])

(loop [curr (z/zipper map? :children (fn [n ch] (assoc n :children (vec ch))) data)]
  (if (z/end? curr)
    (z/root curr)
    (recur (z/next
            (let [node (z/node curr)]
              (if (:id node)
                curr
                (z/replace curr
                           (assoc node :id
                                  (str "id-" (rand-int Integer/MAX_VALUE))))))))))

;;=> {:type "view", 
;;    :children [{:type "view", :id "123"} 
;;               {:type "view", 
;;                :children [{:type "view", :id "id-92807721"}], 
;;                :id "id-1357268462"}], 
;;    :id "id-803083206"}