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 - Fatal编程技术网

Clojure:序列返回到向量

Clojure:序列返回到向量,clojure,Clojure,在序列生成操作(如sort)之后,如何将序列强制转换回向量?在向量序列上使用(vec..)是否成本高昂 一种(坏的?)可能性是创建一个新的向量,但顺序不正确: (vec (sort [1 2 3 4 5 6])) 我这样问是因为我需要随机访问(n..)巨大的排序向量-现在排序后是巨大的序列,具有可怕的O(n)随机访问时间如果需要随机访问具有巨大向量的排序结果,那么调用vec所花费的时间应该远远超过这样做所节省的时间 如果您分析并发现速度太慢,则可能必须使用java数组。根据我自己的测试(没有科

在序列生成操作(如sort)之后,如何将序列强制转换回向量?在向量序列上使用(vec..)是否成本高昂

一种(坏的?)可能性是创建一个新的向量,但顺序不正确:

(vec (sort [1 2 3 4 5 6]))

我这样问是因为我需要随机访问(n..)巨大的排序向量-现在排序后是巨大的序列,具有可怕的O(n)随机访问时间

如果需要随机访问具有巨大向量的排序结果,那么调用vec所花费的时间应该远远超过这样做所节省的时间

如果您分析并发现速度太慢,则可能必须使用java数组。

根据我自己的测试(没有科学依据),如果您进行大量排序,则直接使用数组可能会更好。但是,如果您很少进行排序,并且有很多随机访问要做,那么使用向量可能是更好的选择,因为随机访问时间平均快40%以上,但是由于将向量转换为数组,然后再转换回向量,因此排序性能非常差。以下是我的发现:

(def foo (int-array (range 1000)))

(time
  (dotimes [_ 10000]
    (java.util.Arrays/sort foo)))

; Elapsed time: 652.185436 msecs

(time
  (dotimes [_ 10000]
    (nth foo (rand-int 1000))))

; Elapsed time: 7.900073 msecs

(def bar (vec (range 1000)))

(time
  (dotimes [_ 10000]
    (vec (sort bar))))

; Elapsed time: 2810.877103 msecs

(time
  (dotimes [_ 10000]
    (nth bar (rand-int 1000))))

; Elapsed time: 5.500802 msecs

注意:vector版本实际上并没有在任何地方存储已排序的vector,但这不会显著改变结果,因为在循环中使用简单的绑定可以提高速度。

Meikel Brandmeyer刚刚在Clojure组上发布了一个解决方案

(defn sorted-vec
  [coll]
  (let [arr (into-array coll)]
    (java.util.Arrays/sort arr)
    (vec arr)))
Clojure的
sort
返回排序数组中的seq;这种方法的作用大致相同,但返回的是一个向量,而不是seq

如果愿意,您甚至可以跳过转换回Clojure持久数据结构:

(defn sorted-arr
  "Returns a *mutable* array!"
  [coll]
  (doto (into-array coll)]
    (java.util.Arrays/sort))

但是结果Java数组(在大多数情况下可以将其视为Clojure集合)是可变的。如果您不将其交给其他代码,这很好,但要小心。

作为一名新的Clojure开发人员,很容易混淆集合和序列

此排序向量函数:

(排序[123456]) => (1 2 3 4 5 6) ; 返回一个序列

但是我需要一个向量来进行下一个操作,因为这不起作用

(需要一段时间(部分>3)(123456))

=>ClassCastException java.lang.Long无法强制转换为clojure.lang.IFn user/eval2251(无源文件:2136)

让我们尝试将序列转换为向量:

(vec(123456))

=>ClassCastException java.lang.Long无法强制转换为clojure.lang.IFn user/eval2253(无源文件:2139)

不!但如果你把所有这些都放在一起,效果就很好了

(取while(部分>3)(排序[1 2 3 4 5 6]))

=>(12)

教训:您不能直接使用序列!它们是这一过程的中间步骤。 当REPL尝试求值时(1 2 3 4 5 6),它会看到一个a函数并抛出一个异常:

(123456)
=>ClassCastException java.lang.Long不能强制转换为clojure.lang.IFn user/eval2263(无源文件:2146)

这就是我现在要做的。打电话给vec。但是我想知道是否有更好的方法。现在很容易看出,在排序向量上执行(vec)比排序直接数组慢4倍!向量和数组中的随机访问时间都很快,所以我认为40%无关紧要。应该是java.util.Arrays/sort(他忘记了s)。但是如果它是同一个东西,为什么会快4倍呢?我在Clojure组中发布了计时。至少在服务器VM(您应该使用的)上,它不会快4倍。c、 sort使用显式比较器,并返回seq。它还调用数组,而不是数组:前者返回对象数组,而后者返回类型化数组。除了那些使排序更通用的东西之外,它是相同的代码。这些概括性的做法需要付出代价。这项工作的全部目的是避免某些工作;这就是为什么这个版本更快。这是一条线索,这是误导。在REPL中评估
(排序[123456])
,然后是
(take while(partial>3)*1)
。如果只获取序列的字符串表示形式,则会丢失类型信息。