Dan Jay
Dan Jay

Reputation: 873

Updating a nested map within a vector within a map

I have a map within a vector within a map.

{ :label "Apparel & Accessories", 
  :img_class "itm_3", 
  :children [
             {:id "sub1", 
              :label "Clothing", 
              :markup [:div] 
             } 
             {:id "sub2", 
              :label "Shoes & Footwear", 
              :markup [:div] 
             } 
   ] 
}  `

What I want to do is dissoc the key :markup from all entries. I've been struggling with this for 2 hours. Only far I got is dissoc the key :children. But the requirement is to remove :markup key only.

So final output should be

{ :label "Apparel & Accessories", 
  :img_class "itm_3", 
  :children [
             {:id "sub1", 
              :label "Clothing", 
             } 
             {:id "sub2", 
              :label "Shoes & Footwear", 
             } 
   ]
}   `

Any contribution is highly appreciated.

Upvotes: 1

Views: 696

Answers (4)

Alfred Xiao
Alfred Xiao

Reputation: 1788

If you are sure that you want to remove :markup whenever you see it, here is a simple way to do it:

(def your-data {:your-data "...."})
(clojure.walk/postwalk (fn [m] 
                         (if (map? m) 
                           (dissoc m :markup) 
                           m))
                       your-data)

Upvotes: 1

swlkr
swlkr

Reputation: 310

I solved it in two steps, not one unfortunately.

(def m { :label "Apparel & Accessories", :img_class "itm_3", :children [ {:id "sub1", :label "Clothing", :markup [:div] } {:id "sub2", :label "Shoes & Footwear", :markup [:div] } ] })

(defn dissoc-markup [child]
  (dissoc child :markup))

(update m :children #(mapv dissoc-markup %))

Upvotes: 1

Chris Murphy
Chris Murphy

Reputation: 6509

It is a good habit to make the alteration 'all in one go':

(update m :children (fn [v] (assert (vector? v)) (mapv #(dissoc % :markup) v)))

Here m is only being referred to once. It would matter for instance if you were doing a swap!.

If you don't have a vector, yet want to create one on the fly then this will work:

(update m :children (fn [xs]
                      (->> xs
                           vec
                           (mapv #(dissoc % :markup)))))

But on the other hand there is no real need to be using vectors. The original solution without the assert works fine when :children is set to:

'({:id    "sub1",
  :label  "Clothing",
  :markup [:div]}
 {:id     "sub2",
  :label  "Shoes & Footwear",
  :markup [:div]})

Upvotes: 2

Chris
Chris

Reputation: 23

If your initial map is m, a possible solution is this

(assoc m :children (mapv #(dissoc % :markup) (m :children)))

It takes the value of :children, removes the :markup keys and replaces the result to the initial map.

Upvotes: 0

Related Questions