Initializing elements of a map conditionally in Clojure
You could do something like
(let [not-nils #{:gender}]
(defn create-record [data]
(into {} (for [[k v] {:username (data :username)
:first-name (get-in data [:user-info :name :first])
:last-name (get-in data [:user-info :name :last])
:gender (get-in data [:user-info :sex])}
:when (not (and (nil? v) (not-nils k)))]
[k v]))))
I would use a combination of merge
and when-let
for these optional parameters.
The core idea is to merge in either a single element map or nil for each of the optional parameters. Merging in nil will do nothing, so you won't see the nil in the map.
(defn create-record [data]
(let [res (merge {:username (data :username)
:first-name (get-in data [:user-info :name :first])
:last-name (get-in data [:user-info :name :last])}
(when-let [gender (get-in data [:user-info :sex])]
{:gender gender}))]
res))
Depending on how frequently you need to do this, I would recommend writing a short macro or function around the when-let to keep the code more concise.
(defn create-record [data]
(merge {:username (data :username)
:first-name (get-in data [:user-info :name :first])
:last-name (get-in data [:user-info :name :last])}
(when
(get-in data [:user-info :sex])
{:gender (get-in data [:user-info :sex])})))
Just add when
for each element you want to check if it is not nil
and then it will return a map to be merged or nil that will not affect the return map value.
You can merge several maps together so there is no limit of maps to merge and you can return a separate map for each element that is not nil
.
(cond-> {:username (data :username)
:first-name (get-in data [:user-info :name :first])
:last-name (get-in data [:user-info :name :last])}
(get-in data [:user-info :sex]) (assoc :gender (get-in data [:user-info :sex])))