36

首先,我假设每个特定于结构的序列都有不同的删除项目的方法:向量可以按索引,List可以首先或最后删除,Set应该传递要删除的实际项目,等等。

其次,我假设有一些与结构无关的移除方法;他们在seq接口上工作。

由于序列在 Clojure 中是不可变的,我怀疑您实际上在做的是制作原始的廉价副本,只是没有原始项目。这意味着列表理解可以用于删除,但我怀疑它会不必要地冗长。

请给出一些从 Clojure 序列中删除项目的不同方法的惯用示例。

4

3 回答 3

45

没有一个接口可以从 Clojure 的所有数据结构类型中删除内容,这可能是因为不同的性能特征。

(disj #{:foo :bar} :foo)       ; => #{:bar}
(dissoc {:foo 1 :bar 2} :foo)  ; => {:bar 2}
(pop [:bar :foo])              ; => [:bar]
(pop (list :foo :bar))         ; => (:bar)

这些也有效(返回 a seq):

(remove #{:foo} #{:foo :bar})      ; => (:bar)
(remove #{:foo} [:foo :bar])       ; => (:bar)
(remove #{:foo} (list :foo :bar))  ; => (:bar)

这不适用于哈希映射,因为当您遍历映射时,您会得到键/值对。但这有效:

(remove (fn [[k v]] (#{:foo} k)) {:foo 1 :bar 2})  ; => ([:bar 2])
于 2009-06-02T18:19:52.917 回答
12

查看Clojure 参考中的序列filter并且remove是你所寻求的。

于 2009-06-02T13:24:49.883 回答
2

作为布赖恩·卡珀回答的延伸。这取决于您将如何处理结果。如果您将结果传递给想要处理整个数据集(即打印它)的东西,那么习惯使用 seq 并使用 filter 或 remove 懒惰地解决问题。另一方面,如果您正在修改数据结构以保存以供以后使用,那么在其上创建 seq 将失去其有利的更新特性,因此在这种情况下,最好使用特定于该数据结构的更新函数。

于 2009-06-12T18:05:48.330 回答