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

时间:2015-12-01 10:36:23

标签: list vector clojure

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

( 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]对象,看起来像这样:

([: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中有一种简单的方法吗?

我看过这个帖子How can I remove an item from a sequence in Clojure?

并删除()但我仍然没有。那个帖子显示:

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

但对我来说,我有更多的东西:

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

我想最终得到([:foo:bar])。

3 个答案:

答案 0 :(得分:2)

来自documentation of remove

  

(remove pred) (remove pred coll)

     

返回coll(pred item)返回false的项目的延迟序列。

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

#(= '[circle] %)

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

当然,您也可以将其概括为删除所有元素向量:

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

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

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

我希望你能得到图片:)

答案 1 :(得分:0)

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

(remove (comp symbol? first) 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}])

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

当然,如果你想删除所有只有一个符号值的向量,你应该更具体:

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

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

(filter (comp keyword? first) 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}])

答案 2 :(得分:0)

如果您想编写代码,就像您使用set元素作为remove(或其他一些函数)的谓词一样从线程提供的示例,您只需要把你想要摆脱的元素放在set里面(正如你几乎所做的那样),但你需要知道需要引用的符号。 因此,在上一个示例中,第一个可能的错误原因是不引用向量列表:

(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

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

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

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

 (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}]) 

将清理你的矢量列表。