如何从Clojure的列表中删除某些矢量对象?

 2021-04-26 

How do I remove certain vector objects from a list in Clojure?

我在Clojure中有这样的变量测试:

1
( def test '([:circle {:cx 428, :cy 245, :r 32.2490309931942, :fill red}] [circle] [:line {:x1 461, :y1 222, :x2 365, :y2 163}] [:line {:x1 407, :y1 102, :x2 377, :y2 211}] [line]))

我想从中删除[line]和[circle]对象,并使它看起来像这样:

1
([:circle {:cx 428, :cy 245, :r 32.2490309931942, :fill red}] [:line {:x1 461, :y1 222, :x2 365, :y2 163}] [:line {:x1 407, :y1 102, :x2 377, :y2 211}] )

在Clojure中有一种简单的方法吗?

我已经查看了此线程如何在Clojure中从序列中删除项目?

和remove(),但我仍然没有。该线程显示:

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

但对我来说,我更喜欢:

1
(remove #????? ([:foo :bar] [foo] [bar]))

,我只想以([:: foo:bar])结尾。


摘录自remove

(remove pred) (remove pred coll)

Returns a lazy sequence of the items in coll for which (pred item) returns false.

因此,您需要提供一个这样做的谓词,例如删除[circle]

1
#(= '[circle] %)

这是一个(匿名)函数,用于测试其参数是否等于向量[circle]的(值)。

您当然也可以对此进行概括以删除所有一个元素向量:

1
#(and (vector? %) (= 1 (.length %)))

或删除每个包含至少一个关键字的向量:

1
#(and (vector? %) (not-any? keyword? %))

我希望你能得到照片:)


如果您想像使用线程的set作为您的remove(或某些其他函数)的谓词一样,从线程中提供的示例一样编写代码,则只需将您要放置的元素放在想要摆脱set的内部(就像您几乎已经做过的一样),但是您需要知道需要用引号引起来的符号。
因此,在上一个示例中,第一个可能的错误原因是没有引用向量列表:

1
2
3
(remove #????? ([:foo :bar] [foo] [bar])) ;; this list can not be evaluated and
;; will cause an error
(remove #????? '([:foo :bar] [foo] [bar])) ;; make it a varied list by quoting it

现在您还需要引用#{}内的符号作为谓词:

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

相同的规则也适用于您的第一个示例:

1
2
3
4
 (remove #{['line] ['circle]} test)
 ;;=> ([:circle {:cx 428, :cy 245, :r 32.2490309931942, :fill red}]
 ;;    [:line {:x1 461, :y1 222, :x2 365, :y2 163}]
 ;;    [:line {:x1 407, :y1 102, :x2 377, :y2 211}])

将清理您的载体列表。


在这种情况下,您可能需要这样的东西:

1
(remove (comp symbol? first) test)

输出:

1
2
3
([:circle {:cx 428, :cy 245, :r 32.2490309931942, :fill red}]
 [:line {:x1 461, :y1 222, :x2 365, :y2 163}]
 [:line {:x1 407, :y1 102, :x2 377, :y2 211}])

要删除所有第一个值为symbol的向量。

当然,如果要删除所有带有唯一值(即符号)的向量,则应更具体:

1
2
3
4
(remove #(and (vector? %)
              (== 1 (count %))
              (symbol? (first %)))
        test)

您还可以反转逻辑,而不是删除不需要的数据,而是保留所需的数据:

1
(filter (comp keyword? first) test)

输出:

1
2
3
([:circle {:cx 428, :cy 245, :r 32.2490309931942, :fill red}]
 [:line {:x1 461, :y1 222, :x2 365, :y2 163}]
 [:line {:x1 407, :y1 102, :x2 377, :y2 211}])