在 Clojure 中从另一组中删除一组

use*_*760 0 clojure

(def mine '(a b c))
(def yours '(a b))
(remove yours mine)
 ; should return (c)
Run Code Online (Sandbox Code Playgroud)

有人建议我在另一个线程中使用 remove ,但它不起作用。任何人都可以建议?

Rul*_*lle 5

假设您想从mine中也存在的每个元素中删除yours,有几种方法。您可以将列表转换为集合并使用差异,如下所示:

(require '[clojure.set :refer [difference]])

(def mine '(a b c))
(def yours '(a b))

(difference (set mine) (set yours))
;; => #{c}
Run Code Online (Sandbox Code Playgroud)

但这不会保留从mine. 如果要保留顺序,可以改用remove。为此,我们首先定义一个yours?谓词,当该元素出现在 时,该谓词将为元素返回 true yours

(def yours-set (set yours))
(def yours? (partial contains? yours-set))
Run Code Online (Sandbox Code Playgroud)

如果我们的集合yours只包含像既不是也不是一样的值,我们可以定义它,因为一个集合实现了IFn接口,但是如果包含诸如或@amalloy 指出的元素,这种方法将不起作用。nilfalse(def yours? (set yours))yoursnilfalse

(remove yours? mine)
;; => (c)
Run Code Online (Sandbox Code Playgroud)

上面的代码意味着我们从删除所有元素mine为其yours?计算结果为True。另一种更冗长的方法是使用 remove 的反义词,即filter,并传入谓词的反义词。

(filter (complement yours?) mine)
;; => (c)
Run Code Online (Sandbox Code Playgroud)

但我在这里看不到这种更冗长的方法的好处。

如果你知道你想要一个向量作为结果,你可以改为使用into,传入一个removeing 转换器作为参数。

(into [] (remove yours?) mine)
;; => [c]
Run Code Online (Sandbox Code Playgroud)