Search code examples
clojure

How to merge duplicated keys in list in vectors in Clojure?


My function return for me like this:

 ([:common/to "To" "client/pages/individual_profile.cljs"]
 [:common/to "To" "client/component/edit_experience_dialog.cljs"]
 [:search/advanced-size-b "6 - 50" "client/pages/search/search_conditions.cljs"]
 [:type "Type" "re_frame/signup.cljs"]
 [:type "Type" "re_frame/multiple_jurisdictions.cljs"])

If you can see, I have a duplicated keys in first place in vector like :common/to and :type and I need change this to:

([:common/to "To" "client/pages/individual_profile.cljs" "client/component/edit_experience_dialog.cljs"]
[:search/advanced-size-b "6 - 50" "client/pages/search/search_conditions.cljs"]
[:type "Type" "re_frame/signup.cljs" "re_frame/multiple_jurisdictions.cljs"])

Solution

  • As usual when you have a list of things that you want to correlate by some property, it's a good idea to instead have a map, keyed by that property. Then you will find there are loads of existing tools that easily do what you wanted. In this case, if your data were shaped "right" to begin with, (apply merge-with into ms) would be all you needed.

    (def input '([:common/to "To" "client/pages/individual_profile.cljs"]
     [:common/to "To" "client/component/edit_experience_dialog.cljs"]
     [:search/advanced-size-b "6 - 50" "client/pages/search/search_conditions.cljs"]
     [:type "Type" "re_frame/signup.cljs"]
     [:type "Type" "re_frame/multiple_jurisdictions.cljs"]))
    
    (apply merge-with into
           (for [[k label & vs] input]
             {[k label] (vec vs)}))
    ; => {[:common/to "To"] ["client/pages/individual_profile.cljs" "client/component/edit_experience_dialog.cljs"], 
          [:search/advanced-size-b "6 - 50"] ["client/pages/search/search_conditions.cljs"], 
          [:type "Type"] ["re_frame/signup.cljs" "re_frame/multiple_jurisdictions.cljs"]}