【问题标题】:How do I remove certain vector objects from a list in Clojure?如何从 Clojure 的列表中删除某些矢量对象?
【发布时间】:2015-12-01 10:36:23
【问题描述】:

我在 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() 但我仍然没有它。该线程显示:

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

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

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

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

【问题讨论】:

    标签: list vector clojure


    【解决方案1】:

    来自documentation of remove

    (remove pred)(remove pred coll)

    返回 coll 中的项目的惰性序列,(pred item) 为其返回 false

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

    #(= '[circle] %)
    

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

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

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

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

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

    我希望你得到图片:)

    【讨论】:

    • 谢谢! =) 我不知道你可以使用 #(= '[circle] %) 作为语法!谢谢!
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      如果您想编写代码,就像您从线程提供的示例一样,使用元素的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}]) 
      

      将清理您的向量列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-26
        • 2015-07-27
        • 2019-12-29
        • 1970-01-01
        • 2015-07-12
        • 1970-01-01
        • 2011-10-06
        • 1970-01-01
        相关资源
        最近更新 更多