Sagar
Sagar

Reputation: 3

Iterate SQL result in clojure and update the values

I am learning clojure and am currently stuck at something that would've take a few minutes to solve in an object oriented language. I'm trying to wrap my head around something (possibly trivial?) that I am having trouble understanding. So here goes.

What I've got is a variable that contains the results from a SQL query that I'm making. It contains a list of email addresses that are returned from the DB. So effectively the below def contains a lazy sequence of email addresses.

(def sql-results (... sql call ...)

What I'm trying to do is iterate through sql-results one by one, and change one of the keys (email) in all the rows of the response, from it's current form which is this:

[ 
  { email: [email protected], somekey: somevalue }, 
  { email: [email protected], somekey: somevalue }, 
  { email: [email protected], somekey: somevalue } 
]

to something like this below:

[ 
  { emailAddress: [email protected], somekey: somevalue },   
  { emailAddress: [email protected], somekey: somevalue },   
  { emailAddress: [email protected], somekey: somevalue } 
]

Since I come from Java background, the way I'd do this in Java is pass the sql result object to a method that will iterate through all the rows in the object, change the key for each row from 'email' to 'emailAddress'. The method will return that object with all rows having the modified key value. The calling method will simply assign this changed object to some other variable.

When I try to change the value from 'email' to 'emailAddress' by passing the current row to that function, it returns the formatted value correctly. But at the end of the iteration the new values does not seem to hold.

I understand mutability being the corner stone of clojure. With that and bindings in mind, how do I get around this problem? Should I use something other than doseq? 'for' perhaps? Any ideas or suggestions would do.

This is the code I have currently:

(defn iterate-results [sql-results]
        (doseq [row sql-results]
          (def new-row-value (format-email-key row)) 
          (println "after change ---> " new-row-value) ;This correctly shows the new value of ‘emailAddress’
          [new-row-value] ; I'm not sure how this works
        )

 (println sql-results); This still has pre-change values. I want the new values here.
 )

I think this is the closest problem I could find on SO in the last 2 days to the one I'm having: Clojure - Is it possible to increment a variable within a doseq statement?

Upvotes: 0

Views: 286

Answers (2)

leetwinski
leetwinski

Reputation: 17859

basically the same as @Alan Thompson's variant, but a bit more concise:

user> (map (fn [{:keys [email] :as result}]
             (-> result
                 (dissoc :email)
                 (assoc :email-address email)))
           sql-results)

;;({:somekey "somevalue", :email-address "[email protected]"} 
;; {:somekey "somevalue", :email-address "[email protected]"} 
;; {:somekey "somevalue", :email-address "[email protected]"})

or just using rename-keys function from clojure.set package:

user> (map #(clojure.set/rename-keys % {:email :email-address})
           sql-results)

Upvotes: 1

Alan Thompson
Alan Thompson

Reputation: 29984

(defn normalize-email
  "Change :email key to :email-address"
  [item]
  (let [email-val (:email item)
        item-without-email (dissoc item :email)
        result (assoc item-without-email :email-address email-val)]
    result))

(def data-orig
  [{:email "[email protected]", :somekey :somevalue-1},
   {:email "xyz@:someone.com", :somekey :somevalue-2},
   {:email "[email protected]", :somekey :somevalue-3}])

(mapv normalize-email data-orig) => 

  [{:somekey :somevalue-1, :email-address "[email protected]"}
   {:somekey :somevalue-2, :email-address "xyz@:someone.com"}
   {:somekey :somevalue-3, :email-address "[email protected]"}]

You may wish to get started by looking online at Clojure For the Brave and True and numerous other good Clojure books. Also

Upvotes: 1

Related Questions