通过索引值将2d向量排序为clojure中的延迟序列

时间:2012-01-19 02:57:45

标签: sorting clojure lazy-evaluation

我正在阅读“欢乐的Clojure”,并且遇到了一种快速排序的实现,它使用惰性序列来实现比仅使用延迟序列中的前几个cons细胞时的O(n log n)性能更好的性能。我试图让它为2d数组的整数工作,但我似乎无法得到它: 到目前为止,这就是我所拥有的:

(defn sort-parts2
  "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-parts2 parts)))))))



   sort.joy=> a
    [[5 9 0 6 5 1 4 4 8 7]
     [2 6 8 2 6 7 0 1 8 1]
     [8 8 0 5 9 9 7 7 1 6]
     [9 8 5 3 0 2 0 6 9 3]
     [8 8 5 8 9 8 2 3 8 5]
     [7 9 2 8 5 6 6 8 3 4]
     [4 8 2 4 6 6 7 4 4 1]
     [8 5 1 7 3 0 2 4 2 3]
     [9 1 2 9 0 1 0 2 2 9]
     [4 0 2 6 8 5 6 1 7 7]]

我希望在子向量的第一个元素上输入(sort-parts2 a 0) //索引是:

   sort.joy=> aSorted
     [[2 6 8 2 6 7 0 1 8 1]
     [4 0 2 6 8 5 6 1 7 7]
     [4 8 2 4 6 6 7 4 4 1]
     [5 9 0 6 5 1 4 4 8 7]
     [7 9 2 8 5 6 6 8 3 4]
     [8 5 1 7 3 0 2 4 2 3]
     [8 8 0 5 9 9 7 7 1 6]
     [8 8 5 8 9 8 2 3 8 5]
     [9 1 2 9 0 1 0 2 2 9]
     [9 8 5 3 0 2 0 6 9 3]]

原样,这就是我现在所得到的:

sort.joy=> (sort-parts a)
(0
 1
 4
 4
 5
 5
 6
 7
 8
 9
 [2 6 8 2 6 7 0 1 8 1]
 0
 1
 5
 6
 7
 7
 8
 8
 9
 9
 [9 8 5 3 0 2 0 6 9 3]
 2
 3
 5
 5
 8
 8
 8
 8
 8
 9
 [7 9 2 8 5 6 6 8 3 4]
 1
 2
 4
 4
 4
 4
 6
 6
 7
 8
 [8 5 1 7 3 0 2 4 2 3]
 0
 0
 1
 1
 2
 2
 2
 9
 9
 9
 [4 0 2 6 8 5 6 1 7 7])

有人可以帮我找出一种方法来阻止循环完全解构2d向量,从而返回一个懒惰的向量,头部是行向量吗?我找到了行的比较器,谢谢!

编辑问题的更一般的表述:我想对一个2d向量进行排序,将a看作是一个懒惰的序列,其中头部是下一个有序的子向量通过索引。为了非懒惰,我正在使用:

(defn sortVector 
  "sorts a 2d vector by the given index"
  [index coll]
  (sort-by #(nth % index) coll))

1 个答案:

答案 0 :(得分:1)

如果您从原始文件开始,可以从JoC代码派生sort-parts-by函数,并将smaller?函数替换为比较pivot上某些关键函数的值的函数。另一个项目,而不是直接项目:

(let [pivot-key (keyfn pivot)
      smaller? #(.compare ^java.util.Comparator comp
                          (keyfn %1)
                          pivot-key)]
  ...)

名称keyfncomp来自clojure.core/sort-by - 请参阅其文档字符串/实现以获取预期含义。

请注意,sort-parts不是要在要排序的实际序列上调用 - 你必须首先将它包装在某种seqable中(可能是一个向量);有关示例,请参阅JoC中qsort的定义。您可能希望qsort-by与上面概述的功能一起使用。