I have an ordered map like so:
{:a 1 :b 2 :c 3}
: and given a list of orderings like :
[:c :a]
: I would like to find the simplest way possible to get :
{c: 3 :a 1}
: Does anyone know how to do this?
Update:
(defn asort [amap order] (conj {} (select-keys amap order)))
(asort {:a 1 :b 2 :c 3} [:c :a] )
I would probably convert the vector of orderings into a hash map to quickly look up the ordering index, resulting in something like this:
{ :c 0 :a 1 }
There are a few ways to do that automatically from a seq/vector (e.g. map
with range
, then reduce
into a {} with assoc
). Bind the result of that (or the literal map above) to a local (with let
), let's call it order-map
.
Then filter the entries of the original map (m) to only include the ones included in the ordering:
(select-keys m order)
And put the result of that filtered expression back into a new sorted map (using sorted-map-by
), using a comparator function like the following:
(fn [a b] (compare (order-map a) (order-map b)))
Note that if you didn't actually need it as a map, and a sequence will do, you can use sort-by
with a key function that uses the same order-map.
Putting this together, you get:
(defn asort [m order]
(let [order-map (apply hash-map (interleave order (range)))]
(conj
(sorted-map-by #(compare (order-map %1) (order-map %2))) ; empty map with the desired ordering
(select-keys m order))))
And:
=> (asort (apply sorted-map (interleave (range 0 50) (range 0 50))) (range 32 0 -1))
{32 32, 31 31, 30 30, 29 29, 28 28, 27 27, 26 26, 25 25, 24 24, 23 23, 22 22, 21 21, 20 20, 19 19, 18 18, 17 17, 16 16, 15 15, 14 14, 13 13, 12 12, 11 11, 10 10, 9 9, 8 8, 7 7, 6 6, 5 5, 4 4, 3 3, 2 2, 1 1}
Here's a simple way of doing that:
(defn asort [amap order]
(conj {} (select-keys amap order)))
resulting in:
clojure.core> (asort {:a 1 :b 2 :c 3} [:c :a])
{:c 3, :a 1}
clojure.core> (asort {:a 1 :b 2 :c 3} [:a :c])
{:a 1, :c 3}
Update: as written in the comments, this solution only works for small maps (see HASHTABLE_TRESHOLD
), ultimately relying on hidden implementation details of the underlying data structures. The accepted answer is the proper one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With