如何在Clojure中快速删除矢量中的元素?

Ada*_*old 1 collections optimization clojure data-structures

我正在尝试从Clojure向量中删除元素:

请注意,我正在使用来自Kotlin的Clojure操作

val set = PersistentHashSet.create("foo")
val vec = PersistentVector.create("foo", "bar")
val seq = clojure.`core$remove`.invokeStatic(set, vec) as ISeq
val resultVec = clojure.`core$vec`.invokeStatic(seq) as PersistentVector
Run Code Online (Sandbox Code Playgroud)

这相当于以下Clojure代码:

(remove #{"foo"} ["foo" "bar"])
Run Code Online (Sandbox Code Playgroud)

代码工作正常,但我注意到从seq创建一个向量是极其缓慢的.我写了一个基准,这些是结果:

| Item count | Remove ms | Remove with converting back to vector ms|
-----------------------------------------------------------------
| 1000       | 51        | 1355                                 |
| 10000      | 71        | 5123                                 |
Run Code Online (Sandbox Code Playgroud)

你知道如何将操作seq产生的结果转换removevector没有严格的性能损失吗?

如果不可能有另一种方法来执行remove操作?

Car*_*ate 8

您可以尝试对remove返回向量的补充操作:

(filterv (complement #{"foo"}) 
         ["foo" "bar"])
Run Code Online (Sandbox Code Playgroud)

注意使用filterv. 的v指示,它使用从一开始的矢量,并返回一个矢量,因此不需要转换。它transient在幕后使用了一个向量,所以它应该很快。

我正在否定谓词 usingcomplement所以我可以使用filterv,因为没有removev. remove只是被定义为complementoffilter无论如何,所以它基本上是你已经在做的,只是严格。


ama*_*loy 6

你想要做的事情从根本上表现得很糟糕.向量用于快速索引读/写,O(1)访问右端.要做任何其他事情,你必须拆开矢量并再次重建它,进行O(N)操作.如果您需要这样的操作才能有效,则必须使用不同的数据结构.