Alexander du Sautoy
Alexander du Sautoy

Reputation: 358

Map from list of maps

My problem is next, i have list of maps, for example:

({:id 1 :request-count 10 ..<another key-value pair>..} 
 {:id 2 :request-count 15 ..<another key-value pair>..} 
 ...)

Need create map with records in which, key is value of 'id' and value is value of 'request-count', for each map from prev example, like:

{1 10
 2 15
 ...}

I know how to do this. My question is - standard library have function for achieve this? Or maybe i can achiev this with combination few function, without 'reduce'?

Upvotes: 4

Views: 3954

Answers (2)

Alan Thompson
Alan Thompson

Reputation: 29958

I would do it like so:

(def data
  [{:id 1 :request-count 10}
   {:id 2 :request-count 15}]  )

(defn make-id-req-map [map-seq]
  (vec (for [curr-map map-seq]
         (let [{:keys [id request-count]} curr-map]
           {id request-count}))))

With result:

(make-id-req-map data) => [{1 10} {2 15}]

Note: while you could combine the map destructuring into the for statement, I usually like to label the intermediate values as described in Martin Fowler's refactoring "Introduce Explaining Variable".

Upvotes: 1

tar
tar

Reputation: 1568

Use the juxt function to generate a sequence of pairs, and then toss them into a map:

(into {} (map (juxt :id :request-count) data))

Example:

user=> (def data [{:id 1 :request-count 10 :abc 1}
  #_=>            {:id 2 :request-count 15 :def 2}
  #_=>            {:id 3 :request-count 20 :ghi 3}])
#'user/data
user=> (into {} (map (juxt :id :request-count) data))
{1 10, 2 15, 3 20}

Be aware that if there is more than one map in data with the same :id, then the last one encountered by map will be the one that survives in the output map.

Upvotes: 13

Related Questions