Мне нужно взять 20 результатов из ленивой последовательности миллионов хэш-карт, но чтобы эти 20 были основаны на сортировке по различным значениям в хэш-картах.
Например:
(def population [{:id 85187153851 :name "anna" :created #inst "2012-10-23T20:36:25.626-00:00" :rank 77336}
{:id 12595145186 :name "bob" :created #inst "2011-02-03T20:36:25.626-00:00" :rank 983666}
{:id 98751563911 :name "cartmen" :created #inst "2007-01-13T20:36:25.626-00:00" :rank 112311}
...
{:id 91514417715 :name "zaphod" :created #inst "2015-02-03T20:36:25.626-00:00" :rank 9866}]
В нормальных условиях простая sort-by
работа могла бы выполнить свою работу:
(sort-by :id population)
(sort-by :name population)
(sort-by :created population)
(sort-by :rank population)
Но мне нужно сделать это для миллионов записей как можно быстрее, и я хочу делать это лениво, а не осознавать весь набор данных.
Я много огляделся и нашел несколько реализаций алгоритмов, которые действительно хорошо работают для сортировки последовательности значений (в основном числовых), но не подходят для ленивой последовательности хеш-карт, как мне нужно.
Скорость и эффективность имеют первостепенное значение, лучшее, что я нашел, - это пример быстрой сортировки из Joy Of Clojure (глава 6.4), которая выполняет достаточно работы, чтобы вернуть требуемый результат.
(ns joy.q)
(defn sort-parts
"Lazy, tail-recursive, incremental quicksort. Works against
and creates partitions based on the pivot, defined as 'work'."
[work]
(lazy-seq
(loop [[part & parts] work]
(if-let [[pivot & xs] (seq part)]
(let [smaller? #(< % pivot)]
(recur (list*
(filter smaller? xs)
pivot
(remove smaller? xs)
parts)))
(when-let [[x & parts] parts]
(cons x (sort-parts parts)))))))
(defn qsort [xs]
(sort-parts (list xs)))
Очень хорошо работает ...
(time (take 10 (qsort (shuffle (range 10000000)))))
"Elapsed time: 551.714003 msecs"
(0 1 2 3 4 5 6 7 8 9)
Здорово! Но...
Как бы я ни старался, я не могу понять, как применить это к последовательности хэш-карт.
Мне нужно что-то вроде:
(take 20 (qsort-by :created population))