有没有办法从基于索引的向量中删除项目到现在为止我使用subvec来拆分向量并再次重新创建它。我正在寻找向量的逆转?
答案 0 :(得分:28)
subvec
可能是最好的方法。 Clojure文档说subvec
是“ O(1)并且非常快,因为结果向量与原始向量共享结构,并且没有进行修剪”。另一种方法是走向向量并构建一个新的向量,同时跳过某些元素,这会更慢。
从向量中间移除元素不是向量必然擅长的东西。如果您经常这样做,请考虑使用哈希映射,以便使用dissoc
。
请参阅:
答案 1 :(得分:20)
(defn vec-remove
"remove elem in coll"
[coll pos]
(vec (concat (subvec coll 0 pos) (subvec coll (inc pos)))))
答案 2 :(得分:15)
user=> (def a [1 2 3 4 5])
user=> (time (dotimes [n 100000] (vec (concat (take 2 a) (drop 3 a)))))
"Elapsed time: 1185.539413 msecs"
user=> (time (dotimes [n 100000] (vec (concat (subvec a 0 2) (subvec a 3 5)))))
"Elapsed time: 760.072048 msecs"
Yup - subvec最快
答案 3 :(得分:4)
这是一个很好的解决方案:
(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)
答案 4 :(得分:3)
矢量库clojure.core.rrb-vector
提供对数时间连接和切片。假设你需要持久性,并考虑到你要求的东西,对数时间解决方案就像理论上一样快。特别是,它比使用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]
答案 5 :(得分:2)
获取所需索引可能更快。
(def a [1 2 3 4 5])
(def indexes [0 1 3 4])
(time (dotimes [n 100000] (vec (concat (subvec a 0 2) (subvec a 3 5)))))
"Elapsed time: 69.401787 msecs"
(time (dotimes [n 100000] (mapv #(a %) indexes)))
"Elapsed time: 28.18766 msecs"
答案 6 :(得分:1)
subvec
很快;结合瞬态,它可以提供更好的结果。
使用标准来进行基准测试:
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
的工作台代表:1,368250 ms
,953,565863 µs
,314,387437 µs
。
答案 7 :(得分:0)
另一种可能与任何序列一起工作的可能性,如果指数超出范围则不会轰炸......
(defn drop-index [col idx]
(filter identity (map-indexed #(if (not= %1 idx) %2) col)))