TheRocinante
TheRocinante

Reputation: 4201

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.

Upvotes: 0

Views: 78

Answers (2)

ClojureMostly
ClojureMostly

Reputation: 4713

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})}]]

Upvotes: 1

Michiel Borkent
Michiel Borkent

Reputation: 34820

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

Upvotes: 4

Related Questions