44

我正在寻找一个类似于 assoc-in 但删除键而不是添加键的函数:

(dissoc-in {:a {:b 0}} [:a :b])
;;=> {:a {}}

我爬到这里:

(def m {:a {:b {:c 1}}})

(assoc  m :a (assoc (:a m) :b (dissoc (:b (:a m)) :c)))
;;=> {:a {:b {}}}

但是整个嵌套的东西都弄乱了我的头

4

7 回答 7

114

我用update-in写这个:

(update-in {:a {:b 0 :c 1}} [:a] dissoc :b)

=>

{:a {:c 1}}
于 2014-02-21T18:37:49.400 回答
16

怎么样:

(defn dissoc-in
  "Dissociates an entry from a nested associative structure returning a new
  nested structure. keys is a sequence of keys. Any empty maps that result
  will not be present in the new structure."
  [m [k & ks :as keys]]
  (if ks
    (if-let [nextmap (get m k)]
      (let [newmap (dissoc-in nextmap ks)]
        (if (seq newmap)
          (assoc m k newmap)
          (dissoc m k)))
      m)
    (dissoc m k)))

例子:

(dissoc-in {:a {:b 0 :c 1}} [:a :b])

结果:

{:a {:c 1}}

dissoc-in曾经是一部分clojure.contrib.core,现在是一部分core.incubator


如果要保留空地图,可以稍微更改代码:

(defn dissoc-in
  [m [k & ks :as keys]]
  (if ks
    (if-let [nextmap (get m k)]
      (let [newmap (dissoc-in nextmap ks)]
        (assoc m k newmap))
      m)
    (dissoc m k)))

例子:

(dissoc-in {:a {:b {:c 0}}} [:a :b])

结果:

{:a {}}
于 2013-01-23T20:07:47.953 回答
5

这是基于更新的通用解决方案:

(defn dissoc-in [m p]
  (if (get-in m p) 
    (update-in m
               (take (dec (count p)) p)
               dissoc (last p))
    m))
于 2014-10-06T12:09:59.157 回答
4

受到 Dominic 的代码的启发。我写了一个更简洁的版本

(defn dissoc-in
  [m [k & ks]]
  (if-not ks
    (dissoc m k)
    (assoc m k (dissoc-in (m k) ks))))

(dissoc-in {:a {:b {:c 1}}} [:a :b :c])  ;; => {:a {:b {}}}

另一个版本 dissoc-in2 递归删除空地图

(defn dissoc-in2
  [m [k & ks]]
  (if-not ks
    (dissoc m k)
    (let [nm (dissoc-in2 (m k) ks)]
      (cond (empty? nm) (dissoc m k)
            :else (assoc m k nm)))))


(ut/dissoc-in {:a {:b {:c 3}}} [:a :b :c]) 
;;; => {:a {:b {}}}

(ut/dissoc-in2 {:a {:b {:c 3}}} [:a :b :c]) 
;;=> {}    
于 2013-01-23T20:39:57.850 回答
2

不用写了,clojure.core.incubator已经有了dissoc-in

=> (dissoc-in {:children [{:name "Billy" :age 5}]} [:children 0 :age])
{:children [{:name "Billy"}]}
于 2015-08-07T18:49:19.457 回答
2

我建议dissoc-in混合曲库中使用。

以下是 0.7.0 版的代码:

(defn dissoc-in
  "Dissociate a value in a nested assocative structure, identified by a sequence
  of keys. Any collections left empty by the operation will be dissociated from
  their containing structures."
  [m ks]
  (if-let [[k & ks] (seq ks)]
    (if (seq ks)
      (let [v (dissoc-in (get m k) ks)]
        (if (empty? v)
          (dissoc m k)
          (assoc m k v)))
      (dissoc m k))
    m))

这是medley master 中 dissoc-in 源代码的链接

于 2015-11-08T18:31:48.197 回答
0
(defn dissoc-in [m ks]
  (let [parent-path (butlast ks)
        leaf-key (last ks)]
    (if (= (count ks) 1)
      (dissoc m leaf-key)
      (update-in m parent-path dissoc leaf-key))))
于 2016-12-13T07:40:14.640 回答