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
Vector Clojure在指定位置从向量中删除项_Vector_Clojure - Fatal编程技术网

Vector Clojure在指定位置从向量中删除项

Vector Clojure在指定位置从向量中删除项,vector,clojure,Vector,Clojure,有没有一种方法可以根据索引从向量中删除一个项?现在,我正在使用subvec拆分向量并重新创建它。我正在寻找向量的assoc的反面?subvec可能是最好的方法。Clojure文档说subvec是“O(1)并且非常快,因为生成的向量与原始向量共享结构,并且没有进行修剪”。另一种方法是遍历向量并构建一个新的向量,同时跳过某些元素,这会更慢 从向量的中间删除元素并不是向量必须擅长的事情。如果必须经常这样做,请考虑使用哈希图,这样就可以使用 DISSOC 见: 在clojuredocs.org 在官

有没有一种方法可以根据索引从向量中删除一个项?现在,我正在使用subvec拆分向量并重新创建它。我正在寻找向量的assoc的反面?

subvec
可能是最好的方法。Clojure文档说
subvec
是“O(1)并且非常快,因为生成的向量与原始向量共享结构,并且没有进行修剪”。另一种方法是遍历向量并构建一个新的向量,同时跳过某些元素,这会更慢

从向量的中间删除元素并不是向量必须擅长的事情。如果必须经常这样做,请考虑使用哈希图,这样就可以使用<代码> DISSOC 见:

  • clojuredocs.org
  • 在官方网站指向的
    clojure.github.io

是的-subvec是最快的

这里有一个很好的解决方案iv:

(defn index-exclude [r ex] 
   "Take all indices execpted ex" 
    (filter #(not (ex %)) (range r))) 


(defn dissoc-idx [v & ds]
   (map v (index-exclude (count v) (into #{} ds))))

(dissoc-idx [1 2 3] 1 2)


'(1)

还有一种可能性,它应该适用于任何序列,而不是炸弹,如果指数超出范围

(defn drop-index [col idx]
  (filter identity (map-indexed #(if (not= %1 idx) %2) col)))

subvec
速度快;与瞬变相结合,它提供了更好的结果

使用Criteriam进行基准测试:

user=> (def len 5)
user=> (def v (vec (range 0 5))
user=> (def i (quot len 2))
user=> (def j (inc i))

; using take/drop
user=> (bench
         (vec (concat (take i v) (drop j v))))
;              Execution time mean : 817,618757 ns
;     Execution time std-deviation : 9,371922 ns

; using subvec
user=> (bench
         (vec (concat (subvec v 0 i) (subvec v j len))))
;              Execution time mean : 604,501041 ns
;     Execution time std-deviation : 8,163552 ns

; using subvec and transients
user=> (bench
         (persistent!
          (reduce conj! (transient (vec (subvec v 0 i))) (subvec v j len))))
;              Execution time mean : 307,819500 ns
;     Execution time std-deviation : 4,359432 ns
在更大的长度上,加速比甚至更大;同一台试验台的
len
等于
10000
表示:
1368250 ms
953565863µs
314387437µs
向量库提供对数时间串联和切片。假设您需要持久性,并考虑到您的要求,对数时间解决方案在理论上尽可能快。特别是,它比使用clojure的原生
subvec
的任何解决方案都要快得多,因为
concat
步骤将任何此类解决方案放入线性时间

(require '[clojure.core.rrb-vector :as fv])
(let [s (vec [0 1 2 3 4])]
  (fv/catvec (fv/subvec s 0 2) (fv/subvec s 3 5)))
; => [0 1 3 4]

获取所需的索引可能会更快

(定义a[1 2 3 4 5])
(def索引[0 1 3 4])
(时间(dotimes[n100000](vec(subvec a 0 2)(subvec a 3 5‘‘‘)))
“运行时间:69.401787毫秒”
(时间(dotimes[n 100000](mapv#(a%)索引)))
“运行时间:28.18766毫秒”

对于删除单个项目,这比使用subvec要慢,但是对于删除多个索引,这非常好。对于subvec w/transients版本,您使用了什么clojure版本?追溯到40多年前,有一个for subvec与transient不兼容,因为
APersistentVector$SubVector没有实现IEditableCollection
。我假设这就是为什么这个示例将subvec调用封装在
(vec(subvec…)
中的原因,尽管在我使用clojure 1.7的测试中,
vec
在这种情况下仍然会返回
clojure.lang.apResistentVector$SubVector
,这可能是一种优化,但我还没有深入研究clojure的源代码。我认为是1.6.0。它是在这个答案写出来前几个月发布的。您是否可以更新Clojure 1.8?正如@RyanWilson所提到的,您的瞬态示例不适用于1.8。将上一个示例中的
vec
替换为[]
适用于Clojure 1.8,但这绝对会破坏性能:(.我能得到的最快速度是
(subvec v 0 I)(subvec v j))
,比您在我的电脑上使用subvec中版的
快15%左右…
user=> (def len 5)
user=> (def v (vec (range 0 5))
user=> (def i (quot len 2))
user=> (def j (inc i))

; using take/drop
user=> (bench
         (vec (concat (take i v) (drop j v))))
;              Execution time mean : 817,618757 ns
;     Execution time std-deviation : 9,371922 ns

; using subvec
user=> (bench
         (vec (concat (subvec v 0 i) (subvec v j len))))
;              Execution time mean : 604,501041 ns
;     Execution time std-deviation : 8,163552 ns

; using subvec and transients
user=> (bench
         (persistent!
          (reduce conj! (transient (vec (subvec v 0 i))) (subvec v j len))))
;              Execution time mean : 307,819500 ns
;     Execution time std-deviation : 4,359432 ns
(require '[clojure.core.rrb-vector :as fv])
(let [s (vec [0 1 2 3 4])]
  (fv/catvec (fv/subvec s 0 2) (fv/subvec s 3 5)))
; => [0 1 3 4]