(sort-by keyfn coll) (sort-by keyfn comp coll)
Returns a sorted sequence of the items in coll, where the sort order is determined by comparing (keyfn item). If no comparator is supplied, uses compare. comparator must implement java.util.Comparator. Guaranteed to be stable: equal elements will not be reordered. If coll is a Java array, it will be modified. To avoid this, sort a copy of the array.
user=> (sort-by count ["aaa" "bb" "c"])
("c" "bb" "aaa")
user=> (sort-by first [[1 2] [2 2] [2 3]])
([1 2] [2 2] [2 3])
user=> (sort-by first > [[1 2] [2 2] [2 3]])
([2 2] [2 3] [1 2])
user=> (sort-by :rank [{:rank 2} {:rank 3} {:rank 1}])
({:rank 1} {:rank 2} {:rank 3})
(def x [{:foo 2 :bar 11}
{:bar 99 :foo 1}
{:bar 55 :foo 2}
{:foo 1 :bar 77}])
;sort by :foo, and where :foo is equal, sort by :bar
(sort-by (juxt :foo :bar) x)
;=>({:foo 1, :bar 77} {:bar 99, :foo 1} {:foo 2, :bar 11} {:bar 55, :foo 2})
(def x [{:foo 2 :bar 11}
{:bar 99 :foo 1}
{:bar 55 :foo 2}
{:foo 1 :bar 77}])
; sort-by given key order (:bar)
(def order [55 77 99 11])
(sort-by
#((into {} (map-indexed (fn [i e] [e i]) order)) (:bar %))
x)
;=> ({:bar 55, :foo 2} {:foo 1, :bar 77} {:bar 99, :foo 1} {:foo 2, :bar 11})
;sort entries in a map by value
user=> (sort-by val > {:foo 7, :bar 3, :baz 5})
([:foo 7] [:baz 5] [:bar 3])
;; Warning: You can sort a Java array and get back a sorted immutable Clojure
;; data structure, but it will also change the input Java array, by sorting it.
;; Copy the array before sorting if you want to avoid this.
user=> (def x (to-array [32 -5 4 11]))
#'user/x
user=> (seq x)
(32 -5 4 11)
user=> (def y (sort-by - x))
#'user/y
;; Return sorted sequence
user=> y
(32 11 4 -5)
;; but also modifies x, because it used the array to do the sorting.
user=> (seq x)
(32 11 4 -5)
;; One way to avoid this is copying the array before sorting:
user=> (def y (sort-by - (aclone x)))
#'user/y
;;; from the joy of clojure 2nd
;;; function as arguments
(def plays [{:band "Burial", :plays 979, :loved 9}
{:band "Eno", :plays 2333, :loved 15}
{:band "Bill Evans", :plays 979, :loved 9}
{:band "Magma", :plays 2665, :loved 31}])
(def sort-by-loved-ratio (partial sort-by #(/ (:plays %) (:loved %))))
(sort-by-loved-ratio plays)
;=> ({:band "Magma", :plays 2665, :loved 31}
{:band "Burial", :plays 979, :loved 9}
{:band "Bill Evans", :plays 979, :loved 9}
{:band "Eno", :plays 2333, :loved 15})
;;; others.
(sort-by second [[:a 7], [:c 13], [:b 21]])
;;=> ([:a 7] [:c 13] [:b 21])
(sort-by str ["z" "x" "a" "aa" 1 5 8])
;;=> (1 5 8 "a" "aa" "x" "z")
(sort-by :age [{:age 99}, {:age 13}, {:age 7}])
;;=> ({:age 7} {:age 13} {:age 99})
;; you can pass a comparator to specify the order to sort in
;; typical sort, low to high
(sort-by :value [{:value 1 :label "a"} {:value 3 :label "c"} {:value 2 :label "b"}])
;=> ({:value 1, :label "a"} {:value 2, :label "b"} {:value 3, :label "c"})
;; override the default comparator to sort high to low
(sort-by :value #(> %1 %2) [{:value 1 :label "a"} {:value 3 :label "c"} {:value 2 :label "b"}])
;=> ({:value 3 :label "c"} {:value 2, :label "b"} {:value 1, :label "a"})
;; to sort by nested hash-map values
;; with the help of get-in and custom comparator
> (sort-by #(get-in (val %) [:price]) {:chair {:price 10} :table {:price 9} :lamp {:price 9}})
;;=> ([:table {:price 9}] [:lamp {:price 9}] [:chair {:price 10}])