Soru Clojure için bir dissoc-in komutu nasıl yazılır?


Assoc-in'e benzer bir işlev yazmak istiyorum ancak eklemek yerine anahtarları kaldırır:

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

Buraya geldim:

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

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

ama iç içe geçmiş şey kafamı karıştırıyor


24
2018-01-23 19:50


Menşei


Görmek dev.clojure.org/jira/browse/CLJ-1063 "Orada bir assoc-in olmasına rağmen clojure.core / dissoc-in yoktur." Eylül 2012'de oluşturuldu. - David J.


Cevaplar:


Nasıl hakkında:

(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)))

Örnek:

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

Sonuç:

{:a {:c 1}}

dissoc-in bir zamanlar bir parçasıydı clojure.contrib.coreve şimdi bir parçası core.incubator.


Boş haritalar tutmak istiyorsanız, kodu biraz değiştirebilirsiniz:

(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)))

Örnek:

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

Sonuç:

{:a {}}

10
2018-01-23 20:07



Gerçekten de, insanların boş haritaların kaldırılıp kaldırılmayacağı konusunda kendi tercihleri ​​vardır, bu tartışılmaktadır. Kullanım durumlarımda şimdiye kadar, boş haritaları kaldıran orijinal clojure.contrib.core kodunu (yukarıdaki Dominic tarafından alıntılanmıştır) seçtim. - 0dB
Dokümanlar: github.com/clojure/core.incubator   Mevcut lein koorları [org.clojure / core.incubator ”0.1.3"]. İhtiyacınız içinde "[clojure.core.incubator: cci]" gibi bir şey kullanın, sonra programda: (cci / dissoc-in {: a {: aa 1}: b {: bb 2}} [: a: aa ]) verim {: b {: bb 2}} - Alan Thompson
Gerek yok :as keys, sağ? - Dax Fohl
@ 0dB Sadece boş haritaların kaldırılmasından kaynaklanan bir hata vardı. Haritalardan biri öncelikli bir haritaydı, normal bir harita değil, daha sonra kullanmayı denediğimde ne olduğunu hayal edebiliyorsunuz. (-> bazı harita (dissoc-in [: prio-map 123]) (assoc-in [: prio-map 234] bir şey)) - oskarkv


Bunu kullanarak yazarım güncelleştirmek-in:

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

=>

{:a {:c 1}}

78
2018-02-21 18:37





Dominic'in kodundan esinlenerek. Daha kısa bir versiyon yazdım.

(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 {}}}

Başka bir sürüm dissoc-in2 boş haritaları yinelemeli olarak kaldırır

(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]) 
;;=> {}    

4
2018-01-23 20:39





Güncellemeye dayalı genel bir çözüm:

(defn dissoc-in [m p]
  (if (get-in m p) 
    (update-in m
               (take (dec (count p)) p)
               dissoc (last p))
    m))

4
2017-10-06 12:09



Kullanabilir (drop-last p) yerine (take...). (Veya butlastama bu cesaret kırılabilir.) - eyelidlessness


Kullanmanı tavsiye ederim dissoc-in itibaren medley kütüphanesi.

İşte 0.7.0 sürümündeki kod:

(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))

İşte bir medley master'daki dissoc-in kaynak koduna bağlantı.


1
2017-11-08 18:31





Bir tane yazmaya gerek yok. clojure.core.incubator zaten var dissoc-in:

=> (dissoc-in {:children [{:name "Billy" :age 5}]} [:children 0 :age])
{:children [{:name "Billy"}]}

0
2017-08-07 18:49





(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))))

0
2017-12-13 07:40



Bu kod pasajı soruyu çözebilirken bir açıklama dahil Gönderinizin kalitesini iyileştirmeye gerçekten yardımcı olur. Gelecekte okuyucular için soruyu cevapladığınızı ve bu kişilerin kod önerilerinizin nedenini bilmeyebileceğini unutmayın. - DimaSan