Skip to content

Instantly share code, notes, and snippets.

@rauhs
Last active June 23, 2020 05:38
Show Gist options
  • Save rauhs/913330d7f75841b013b3cf6115693687 to your computer and use it in GitHub Desktop.
Save rauhs/913330d7f75841b013b3cf6115693687 to your computer and use it in GitHub Desktop.
(defn sort-by-fast
"Returns a sorted sequence of the items in coll, where the sort
order is determined by comparing (keyfn item). Comp can be
boolean-valued comparison funcion, or a -/0/+ valued comparator.
Comp defaults to compare."
([keyfn coll]
(sort-by-fast keyfn compare coll))
([keyfn comp coll]
(let [arr (to-array coll)
;; Hack: access private function:
cmp (js/cljs.core.fn__GT_comparator comp)]
(dotimes [idx (alength arr)]
(let [el (aget arr idx)]
(aset arr idx #js[(keyfn el) idx el])))
(garray/sort arr
(fn [a b]
(or ^boolean (cmp (aget a 0) (aget b 0)) (- (aget a 1) (aget b 1)))))
(dotimes [idx (alength arr)]
(let [el (aget arr idx)]
(aset arr idx (aget el 2))))
(seq arr))))
(simple-benchmark
[xs (repeatedly 1000 #(-> {:x (rand-int 1000)}))]
(sort-by-fast :x xs)
100)
(simple-benchmark
[xs (repeatedly 1000 #(-> {:x (rand-int 1000)}))]
(sort-by :x xs)
100)
;; => ~5x speedup
@rauhs
Copy link
Author

rauhs commented Jan 10, 2017

Also handy convenience macro amap-inplace:

(defmacro amap-inplace
  "Maps an expression across an array a, using an index named idx, and
  element el:
  (amap-inplace arr idx el [idx el])"
  [a idx ret expr]
  `(let [a# ~a]
     (dotimes [~idx (alength a#)]
       (let [~ret (aget a# ~idx)]
         (aset a# ~idx ~expr)))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment