Search code examples
clojurering

How to add keys to a map / create keys in current map clojure


I have the following map from a get request

:form-params {"qu" ["2015 Q2" "2015 Q3" "2015 Q4" "2015 Q2"
                    "2015   Q3" "2015 Q4" "2015 Q2" "2015 Q3"
                    "2015 Q4" "2015 Q2" "2015 Q3" "2015 Q4"],
              "sh" ["2580" "2580" "2580" "2983"
                    "2983" "2983" "53" "53"
                    "53" "4558" "4558" "4558"],
              "prin" ["191" "191" "191" "191"
                      "191" "191" "191" "191"
                      "191" "191" "191" "191"],
              "bu" ["" "" "" "" "" "" "" "" "" "" "" ""]}

I would like to create the keys :quarter, :sh, :prin, and :bu. The reason is from here I was going to parition into 4 groups and interleave like below

 (let [params (:form-params request)
                   data (partition 4 (interleave (:quarter params) (:shiptoid params)
                                                 (:principalid params) (:budget params)
                                                  ))

Thanks!


Solution

  • The built in function clojure.set/rename-keys will do this nicely, though like all things in clojure there are several approaches. So lets walk through the process. What you have is very close to working. If I just lookup each by it's original string key, we can see it work:

    user> (def request {:form-params {"qu" ["2015 Q2" "2015 Q3" "2015 Q4" "2015 Q2"
                                            "2015   Q3" "2015 Q4" "2015 Q2" "2015 Q3"
                                        "2015 Q4" "2015 Q2" "2015 Q3" "2015 Q4"],
                                  "sh" ["2580" "2580" "2580" "2983"
                                        "2983" "2983" "53" "53"
                                        "53" "4558" "4558" "4558"],
                                  "prin" ["191" "191" "191" "191"
                                          "191" "191" "191" "191"
                                          "191" "191" "191" "191"],
                                  "bu" ["" "" "" "" "" "" "" "" "" "" "" ""]}})
    #'user/request
    user> (let [params (:form-params request)
                data (partition 4 (interleave (params "qu") (params "sh")
                                              (params "prin") (params "bu")))]
            (clojure.pprint/pprint data))
    (("2015 Q2" "2580" "191" "")
     ("2015 Q3" "2580" "191" "")
     ("2015 Q4" "2580" "191" "")
     ("2015 Q2" "2983" "191" "")
     ("2015   Q3" "2983" "191" "")
     ("2015 Q4" "2983" "191" "")
     ("2015 Q2" "53" "191" "")
     ("2015 Q3" "53" "191" "")
     ("2015 Q4" "53" "191" "")
     ("2015 Q2" "4558" "191" "")
     ("2015 Q3" "4558" "191" "")
     ("2015 Q4" "4558" "191" ""))
    

    now it sound like you want a map that is just like the first map, except it has different keys pointing to the same values. To accomplish this we can create this new map using a map literal easily and efficiently:

    user> (def new-request
            (let [params (:form-params request)]
              {:form-params {:quarter (params "qu")
                             :shiptoid (params "sh")
                             :principalid (params "prin")
                             :budget (params "bu")}}))
    #'user/new-request
    user> (let [params (:form-params new-request)
                data (partition 4 (interleave (:quarter params) (:shiptoid params)
                                              (:principalid params) (:budget params)))]
            (clojure.pprint/pprint data))
    (("2015 Q2" "2580" "191" "")
     ("2015 Q3" "2580" "191" "")
     ("2015 Q4" "2580" "191" "")
     ("2015 Q2" "2983" "191" "")
     ("2015   Q3" "2983" "191" "")
     ("2015 Q4" "2983" "191" "")
     ("2015 Q2" "53" "191" "")
     ("2015 Q3" "53" "191" "")
     ("2015 Q4" "53" "191" "")
     ("2015 Q2" "4558" "191" "")
     ("2015 Q3" "4558" "191" "")
     ("2015 Q4" "4558" "191" ""))
    

    and to make it more automatic you can use update-in:

    user> (def new-request
            (update-in request [:form-params]
                       (fn [params] {:quarter (params "qu")
                                     :shiptoid (params "sh")
                                     :principalid (params "prin")
                                     :budget (params "bu")})))
    #'user/new-request
    user> (let [params (:form-params new-request)
                data (partition 4 (interleave (:quarter params) (:shiptoid params)
                                              (:principalid params) (:budget params)))]
            (clojure.pprint/pprint data))
    (("2015 Q2" "2580" "191" "")
     ("2015 Q3" "2580" "191" "")
     ("2015 Q4" "2580" "191" "")
     ("2015 Q2" "2983" "191" "")
     ("2015   Q3" "2983" "191" "")
     ("2015 Q4" "2983" "191" "")
     ("2015 Q2" "53" "191" "")
     ("2015 Q3" "53" "191" "")
     ("2015 Q4" "53" "191" "")
     ("2015 Q2" "4558" "191" "")
     ("2015 Q3" "4558" "191" "")
     ("2015 Q4" "4558" "191" ""))
    

    starting in clojure 1.7 (the next release as of today) you can also use the update function, which is slightly more elegant. though this can still be made slightly more elegant by adding the clojure.set library and using the built in rename-keys function:

    user> (def new-request
            (update request :form-params
                    clojure.set/rename-keys {"qu" :quarter
                                             "sh" :shiptoid
                                             "prin" :principalid
                                             "bu" :budget}))
    #'user/new-request
    user> (let [params (:form-params new-request)
                data (partition 4 (interleave (:quarter params) (:shiptoid params)
                                              (:principalid params) (:budget params)))]
            (clojure.pprint/pprint data))
    (("2015 Q2" "2580" "191" "")
     ("2015 Q3" "2580" "191" "")
     ("2015 Q4" "2580" "191" "")
     ("2015 Q2" "2983" "191" "")
     ("2015   Q3" "2983" "191" "")
     ("2015 Q4" "2983" "191" "")
     ("2015 Q2" "53" "191" "")
     ("2015 Q3" "53" "191" "")
     ("2015 Q4" "53" "191" "")
     ("2015 Q2" "4558" "191" "")
     ("2015 Q3" "4558" "191" "")
     ("2015 Q4" "4558" "191" ""))