2
votes

I have a sequence that looks like this: ({:a 1 :b "lorem"} {:a 2 :b "ipsum"}) and I want to convert that to a map of maps using the value of :a as the value of the key in the new map. The result I am expecting is {:1 {:a 1 :b "lorem"} :2 {:a 2 :b "ipsum"}}.

And maybe this is not idiomatic clojure, I'm still learning. I basically receive a large sequence, and I will be looking up values in this sequence by a certain value in each map, and I want to use a map to make it O(1).

In C#, on an IEnumerable, you can call .ToDictionary(x => x.SomeProperty) which would return a Dictionary of key value pairs, using the value of SomeProperty as the key. And this has lookup performance of O(1) instead of the typical O(N) for a list/sequence.

1

1 Answers

3
votes

This should do the transform you are after:

(def latin '({:a 1 :b "lorem"} {:a 2 :b "ipsum"}))

(defn transform [kw in]
  (zipmap (map kw in) in))

=> (transform :a latin)
{1 {:a 1, :b "lorem"}, 2 {:a 2, :b "ipsum"}}

I hesitated in changing the number to a keyword, as not sure as to the reason you would want to do that...

... edit - because you can always do an indexed (O(1)) retrieve like so:

(get (transform :a latin) 1)

1 doesn't work at the front because it can't be used as a function (unlike :1), however get is a function whose second argument is the search key when the first argument is a map.