Clojure:从集合中删除给定节点的函数

时间:2013-09-18 01:47:19

标签: clojure

我想要一个从包含该节点的集合中删除任何节点(子集合)的函数。

(def coll {:a ["b" {:c "d" :e ["f" {:g "h"}]}]})
(def node {:g "h"})

什么是一个好的删除节点功能?

(remove-node coll node)
;=> {:a ["b" {:c "d" :e ["f"]}]})

谢谢!

编辑: 我想要做的是删除一个enlive-node

(def enlive-node
  [{:type :dtd, :data ["html" nil nil]} 
   {:tag :html, 
    :attrs nil, 
    :content ["\n" 
              {:tag :head, 
               :attrs nil, 
               :content ["\n    \n    " 
                         {:tag :title, 
                          :attrs nil, 
                          :content ["Stack Overflow"]} 
                         "\n    " 
                         {:tag :link, 
                          :attrs {:href "//cdn.sstatic.net/stackoverflow/img/favicon.ico", 
                                  :rel "shortcut icon"}, 
                                  :content nil}]}]}])

要删除的节点始终是字符串或整个哈希映射。

(remove-node enlive-node {:tag :title, 
                              :attrs nil, 
                              :content ["Stack Overflow"]})

1 个答案:

答案 0 :(得分:3)

对于您的示例,您可以使用clojure.walk/postwalk遍历散列图并删除节点。

(require '[clojure.walk :as walk])

(defn remove-node [coll target]
  (walk/postwalk
    (fn [item]
      (if (vector? item)
        (filterv #(not= target %) item)
        item))
    coll))

(remove-node coll node)

修改

从您更新的问题,看起来您正在使用Enlive节点集合。在您的情况下,另一个解决方案是生成Enlive节点选择器并使用net.cgrand.enlive-html/at*函数转换集合。

(require '[net.cgrand.enlive-html :as e])

(defn gen-transform [target]
  [[(cond
     (string? target) e/text-node
     (map? target) (:tag target)
     :else e/any-node)]
   #(when (not= target %) %)])

(defn remove-node [coll & nodes]
  (e/at* coll (map gen-transform nodes)))

(remove-node enlive-node
             {:tag :title, :attrs nil, :content ["Stack Overflow"]}
             "\n")