简体   繁体   中英

Updating a map that is nested a couple layers in lists in clojure

I'm new to functional programming, and I am trying to figure out how to achieve the following.

I have a data structure as so in Clojure:

  [
    [
      { 
        :key1 "val1",
        :key2 [
                { :type "D", ... },
                { :type "A", ... },
                { :type "B", ...}
              ]
         ...
       }
    ]
  ]

What I want to do is keep the same overall data structure with all of it's data. However, I want the objects in "key2" list to be sorted by "type".

After reading some tutorials, I have this much:

(doseq [currentList myDataStructure]
  (doseq [currentItem currentList]
    (println (get currentItem :key2))
)))

By the way, is doseq an alright way to iterate through lists? I see Clojure otherwise does looping through data structures through recursion. Seemed kind of odd to me to add frames to the stack just to iterate through a list.

You can do this with update-in :

(def x  [[{:key1 "val1",
           :key2 [{:type "D"}
                  {:type "A"}
                  {:type "B"}]}]])

(update-in x [0 0 :key2] (partial sort-by :type))

This is perfect use-case for specter :

(sp/transform [sp/FIRST sp/ALL :key2] (partial sort-by :type)
  [
   [
    {
     :key1 "val1",
     :key2 [{:type "D", :v 1},
            {:type "A", :v 3},
            {:type "B", :v 89}]}
    {
     :key1 "val3",
     :key2 [{:type "Z", :v 10},
            {:type "A", :v 30},
            {:type "B", :v 890}]}
    ]
   ])
;;=> [[{:key1 "val1", :key2 ({:type "A", :v 3} {:type "B", :v 89} {:type "D", :v 1})}

;;     {:key1 "val3", :key2 ({:type "A", :v 30} {:type "B", :v 890} {:type "Z", :v 10})}]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM