Friday, March 17, 2017

Sorting maps in Clojure

Problem 

If you like to keep data in maps in ClojureScript to be able to access it fast, but also need sorting, maybe you should read this.

 Cause

 Let's say you have a map like:

 (def a {:0 0, :1 1, :2 2, :3 3, :4 4, :5 5, :6 6, :7 7}) 
 (vals a) would return: (0 1 2 3 4 5 6 7) 

 But what about

 (def a {:0 0, :1 1, :2 2, :3 3, :4 4, :5 5, :6 6, :7 7, :8 8}) 

 where

 (vals b) returns: (6 7 4 5 1 0 3 2 8) 

 The trick is how data is represented internally. If the number of pairs is less then 8 then (type a) is a clojure.lang.PersistentArrayMap but (type b) is a clojure.lang.PersistentHashMap which is optimized for access, but loses order as a compromise.

 If we generate our maps using a function:

 (defn gen [x] (doall (map (fn [x] [(keyword (str x)) x]) (range x)))) try: 

 (->> (gen 8) 
         (into {}) 
          type ) 

 (->> (gen 9) 
         (into {}) 
          type ) 

and you'll see for yourself.

No comments: