Reputation: 4257
I am trying to sort a map by a key value. Given this map:
{:1 {:bar "something" :rank 10} :2 {:bar "other" :rank 20}}
I like to sort it by rank
value:
{:2 {:bar "other" :rank 20} :1 {:bar "something" :rank 10} }
Its possible using sort-by
?
Thanks in advance
Upvotes: 3
Views: 1515
Reputation: 14549
The other answers will work, but if you are going to be doing this command a lot, then you would be better off storing the data in a data.priority-map. It is designed for situations just like this.
A priority map is very similar to a sorted map, but whereas a sorted map produces a sequence of the entries sorted by key, a priority map produces the entries sorted by value.
; You'll need to add [org.clojure/data.priority-map "0.0.7"] to :dependencies first
user=> (require '[clojure.data.priority-map :as pm])
; nil
user=> (pm/priority-map-keyfn-by :rank >
:1 {:bar "something" :rank 10}
:2 {:bar "other" :rank 20})
; {:2 {:rank 20, :bar "other"}, :1 {:rank 10, :bar "something"}}
Upvotes: 4
Reputation: 9886
See also this answer
Ascending:
user=> (sort-by (comp :rank second) < {:1 {:bar "something" :rank 10} :2 {:bar "other" :rank 20} :3 {:bar "bar" :rank 15}})
([:1 {:bar "something", :rank 10}] [:3 {:bar "bar", :rank 15}] [:2 {:bar "other", :rank 20}])
Descending:
user=> (sort-by (comp :rank second) > {:1 {:bar "something" :rank 10} :2 {:bar "other" :rank 20} :3 {:bar "bar" :rank 15}})
([:2 {:bar "other", :rank 20}] [:3 {:bar "bar", :rank 15}] [:1 {:bar "something", :rank 10}])
These both return the sequence of elements of map, to convert back to a map again, wrap it in (into {} ...)
Upvotes: 2
Reputation: 3074
sort-by takes a key function as well as an optional custom comparator
; keyfn comparator
(sort-by (comp :rank second) >
{:1 {:bar "something" :rank 10} :2 {:bar "other" :rank 20}})
;=> ([:2 {:bar "other", :rank 20}] [:1 {:bar "something", :rank 10}])
Upvotes: 3
Reputation: 106400
It's simple enough to do with sort-by
, but since that sorts in ascending order, you'll have to use reverse
to get it to go the right way.
(reverse
(sort-by (comp :rank second)
{:1 {:bar "something" :rank 10} :2 {:bar "other" :rank 20}}))
Upvotes: 3