Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
clojure中散列映射的惰性序列排序_Clojure_Hashmap_Quicksort_Lazy Sequences - Fatal编程技术网

clojure中散列映射的惰性序列排序

clojure中散列映射的惰性序列排序,clojure,hashmap,quicksort,lazy-sequences,Clojure,Hashmap,Quicksort,Lazy Sequences,我需要从数以百万计的散列映射的惰性序列中获取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" :ran

我需要从数以百万计的散列映射的惰性序列中获取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 :id population)
(sort-by :name population)
(sort-by :created population)
(sort-by :rank population)
但我需要尽可能快地跨数百万条记录执行此操作,并且希望以懒散的方式执行此操作,而不必实现整个数据集

我环顾四周,发现了许多算法的实现,它们对值序列(主要是数字)的排序效果非常好,但对于散列映射的延迟序列,它们都没有达到我所需要的效果

速度和效率是最重要的,我所发现的最好的例子是书中的快速排序示例(第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))) 
太好了!但是

无论我做了多少尝试,我似乎都不知道如何将其应用到哈希映射序列中

我需要像这样的东西:

(take 20 (qsort-by :created population))

如果只需要前N个元素,则完整排序的代价太高(即使是JoC中的惰性排序:它也需要将几乎所有的数据集保留在内存中)

您只需扫描(
减少
)数据集,并保留迄今为止最好的N项

=> (defn top-by [n k coll]
     (reduce
      (fn [top x]
        (let [top (conj top x)]
          (if (> (count top) n)
            (disj top (first top))
            top)))
      (sorted-set-by #(< (k %1) (k %2))) coll))
#'user/top-by
=> (top-by 3 first [[1 2] [10 2] [9 3] [4 2] [5 6]])
#{[5 6] [9 3] [10 2]}
=>(由[n k coll]定义顶部)
(减少
(fn[前十名]
(让[top(conj top x)]
(如果(>(计数顶部)n)
(disj顶部(第一顶部))
(上)
(按#(<(k%1)(k%2)))coll)排序)
#'用户/top by
=>(排名靠前3位[[12][102][93][42][56])
#{[5 6] [9 3] [10 2]}

如果您只需要前N个元素,则完整排序的成本太高(即使是像JoC中那样的惰性排序:它也需要将几乎所有的数据集保留在内存中)

您只需扫描(
减少
)数据集,并保留迄今为止最好的N项

=> (defn top-by [n k coll]
     (reduce
      (fn [top x]
        (let [top (conj top x)]
          (if (> (count top) n)
            (disj top (first top))
            top)))
      (sorted-set-by #(< (k %1) (k %2))) coll))
#'user/top-by
=> (top-by 3 first [[1 2] [10 2] [9 3] [4 2] [5 6]])
#{[5 6] [9 3] [10 2]}
=>(由[n k coll]定义顶部)
(减少
(fn[前十名]
(让[top(conj top x)]
(如果(>(计数顶部)n)
(disj顶部(第一顶部))
(上)
(按#(<(k%1)(k%2)))coll)排序)
#'用户/top by
=>(排名靠前3位[[12][102][93][42][56])
#{[5 6] [9 3] [10 2]}

太棒了!非常感谢。好极了非常感谢。