Bill O'Brien
Bill O'Brien

Reputation: 882

Clojure: create vector of maps from list

I want to create a vector of maps like this:

[{:patid 0} {:patid 1} {:patid 2}]
=> [{:patid 0} {:patid 1} {:patid 2}]

How would I create a vector of n maps? The closest I've gotten is this:

(defn patientid [n]
    (interleave (repeat n :patid) (range n)))

(patientid 3)
=> (:patid 0 :patid 1 :patid 2)

Is there a function to convert this list into maps?

Upvotes: 0

Views: 1324

Answers (3)

Pradeep Kumar Tiwari
Pradeep Kumar Tiwari

Reputation: 166

The most efficient way would be this:-

(defn generate-n [n]
  (persistent! (loop [out (transient []) x 0]
                 (if (< x n)
                   (recur (conj! out {:patient-id x}) (inc x))
                   out)))
  )

Here are some tests results:-

user=> (time (mapv (fn [n] {:patient-id n}) (range 5)))
"Elapsed time: 0.476472 msecs"
[{:patient-id 0} {:patient-id 1} {:patient-id 2} {:patient-id 3} {:patient-id 4}]

user=> (time (mapv (fn [n] {:patient-id n}) (range 5)))
"Elapsed time: 0.1545 msecs"
[{:patient-id 0} {:patient-id 1} {:patient-id 2} {:patient-id 3} {:patient-id 4}]

user=> (time (mapv (fn [n] {:patient-id n}) (range 5)))
"Elapsed time: 0.143853 msecs"
[{:patient-id 0} {:patient-id 1} {:patient-id 2} {:patient-id 3} {:patient-id 4}]

user=> (time (mapv (fn [n] {:patient-id n}) (range 5)))
"Elapsed time: 0.163187 msecs"
[{:patient-id 0} {:patient-id 1} {:patient-id 2} {:patient-id 3} {:patient-id 4}]

With loop recur :-

user=> (time (generate-n 5))
"Elapsed time: 0.033539 msecs"
[{:patient-id 0} {:patient-id 1} {:patient-id 2} {:patient-id 3} {:patient-id 4}]

user=> (time (generate-n 5))
"Elapsed time: 0.032465 msecs"
[{:patient-id 0} {:patient-id 1} {:patient-id 2} {:patient-id 3} {:patient-id 4}]

user=> (time (generate-n 5))
"Elapsed time: 0.031155 msecs"
[{:patient-id 0} {:patient-id 1} {:patient-id 2} {:patient-id 3} {:patient-id 4}]

Upvotes: 0

Alan Thompson
Alan Thompson

Reputation: 29984

I like to keep it simple:

(def map-list
  (for [i (range 5)]
    {:patient-id i}))
(println map-list)

=> ({:patient-id 0} {:patient-id 1} {:patient-id 2} {:patient-id 3} {:patient-id 4})

If you want it in a vector (my favorite) instead of a lazy list, use vec:

(def map-vec (vec map-list))
(println map-vec)

=> [{:patient-id 0} {:patient-id 1} {:patient-id 2} {:patient-id 3} {:patient-id 4}]

Upvotes: 1

Taylor Wood
Taylor Wood

Reputation: 16194

This should do the trick:

(mapv (partial hash-map :patient-id) (range 3))
=> [{:patient-id 0} {:patient-id 1} {:patient-id 2}]

This is mapping (mapv to return a vector as requested) over a range of integers, and creating a map for each one. hash-map is a function that takes key/value pairs, and this uses partial to create a partial function (that's only missing the number). For example, this is slightly longer but functionally equivalent and maybe easier to understand using a map literal:

(mapv (fn [n] {:patient-id n}) (range 3))

Upvotes: 4

Related Questions