1

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.

1

4 Answers 4

2

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]})
Sign up to request clarification or add additional context in comments.

8 Comments

I think my map is Lazy. With your solution I get an error "ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.Associative"
AssertionError Assert failed: (vector? v)
So your data is different to that in your question. You can use into [] to change your data. But I'll take out the assert and make it work locally...
Data not much different but bigger. Some has many data within :children some has nil.
By the way a map can't be lazy. I think the problem is that where you think there are maps there are really seqs.
|
1

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

Comments

1

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)

Comments

0

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.

1 Comment

I get an error "ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IFn"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.