如何从可变向量中删除元素?

How to remove element from mutable vector?

我知道如何创建可变向量:

(defn create-vector []
  (intern *ns* (symbol "my-vector" (ref []))
=>my-namespace/my-vector

我知道如何向该向量添加元素:

(dosync (alter my-vector conj "test"))
=>["test"]

现在我的可变向量中有 "test" 个字符串。但是我怎样才能删除它呢?我尝试使用惰性序列函数 remove

(dosync (alter my-vector remove "test"))

但它不起作用。如何从可变向量中删除元素?

编辑: 集合不一定非得是矢量。我找到了 set 的解决方案,但如果有人建议 vector 的解决方案,我会等待。

你的错误是你将 "test" arg 传递给 remove 函数,而它实际上接受了一个谓词。在你的情况下,这一个 wold 工作(虽然不正确,制作列表而不是向量):

(dosync (alter my-vector #(remove #{"test"} %)))

要使其成为向量,您必须这样做:

(dosync (alter my-vector #(vec (remove #{"test"} %))))

是什么让我对你的例子感到好奇:

  1. 为什么要使用这种奇怪的结构:

    (defn create-vector []
      (intern *ns* (symbol "my-vector" (ref []))))
    

    而不只是 (def my-vector (ref []))

  2. 你为什么要使用 ref?你会在一些交易中使用它吗?如果不是,我会建议你移动到 atom(因为它也是线程安全的)

    user> (def my-atom (atom []))
    #'user/my-atom
    
    user> (swap! my-atom conj "hello")
    ["hello"]
    
    user> (swap! my-atom #(remove #{"hello"} %))
    ()
    

正如我在编辑中指定的那样,集合不一定是真正的矢量。 @leetwinski 发布了关于如何为矢量执行此操作的答案,但如果我决定使用 set,我会找到其他解决方案。因此,如果我们以与问题相同的方式创建集合,将 [] 替换为 #{}:

(defn create-vector []
  (intern *ns* (symbol "my-set" (ref #{}))
=>my-namespace/my-vector

并添加元素:

(dosync (alter my-set conj "test"))
=>#{"test"}

,我们可以删除它

(dosync (alter my-set disj item))
=>#{}