【问题标题】:Loop through vector of vectors and remove element from vector in Clojure循环遍历向量的向量并从 Clojure 中的向量中删除元素
【发布时间】:2019-08-20 10:32:51
【问题描述】:

我是 clojure 编程的新手,需要一些代码方面的帮助。我有这个向量的向量,如下所示,

(def start-pos [[[:fox :goose :corn :you] [:boat] []]])

我想遍历向量并从内部向量之一中删除一个元素,例如从 start-pos 中删除 ':goose'。

我尝试了下面的代码,但由于某种原因它没有按预期工作,

(map #(disj (set %) :goose) start-pos)

结果却是,

(#{[:boat] [] [:fox :goose :corn :you]})

从结果中可以看出,内部向量现在是一个集合,是的,原始顺序被扭曲了,有没有办法删除元素而不打乱向量的原始顺序,也许不需要将其转换为先来一套?我首先选择将此转换为集合,因为根据文档disj 仅适用于集合。

补充:这篇文章与this suggested post 不相似,因为我的向量嵌套了三个向量。

【问题讨论】:

标签: clojure clojurescript


【解决方案1】:

内部向量现在是一个集合

那是因为#(disj (set %) :goose) 的结果返回了一个集合。

原来的顺序被扭曲了

默认情况下,集合不保留插入顺序,类似于超过 8 个键的地图。

我想循环遍历该向量并从其中一个内部向量中删除一个元素,例如从 start-pos 中删除 ':goose'。

通过谓词从集合中删除元素所需的函数称为remove,但是...

您要删除的值实际上是嵌套在start-pos 深处的三个向量,因此您需要对每个内部向量进行额外的迭代,以此类推,如果您想递归地从每个向量中删除关键字:goose .这是使用clojure.walk的借口:

(clojure.walk/postwalk
  (fn [v]
    (if (coll? v)
      (into (empty v) (remove #{:goose}) v)
      v))
  start-pos)
=> [[[:fox :corn :you] [:boat] []]]

这会遍历start-pos 中的每个值,从它找到的任何集合中删除:goose

【讨论】:

  • 感谢您的回复,工作。我还意识到嵌套向量的嵌套三次是一个错误,而我的意图是 (def start-pos [[:fox :goose :corn :you] [:boat] []]) 。之后我的代码工作了。谢谢你,以后肯定会需要它
【解决方案2】:

这是一种不太灵活的方法,我为了自己的利益做了更多的事情(学习 Clojure)

(update-in
  start-pos
  [0 0]
  #(vec (concat
          (subvec % 0 1)
          (subvec % (inc 1)))))

它手动导航并重构 :goose 级别的关键字,使其内部没有 :goose

我认为解决这个问题的一些替代方法包括 Spectre 和 Zippers

【讨论】:

  • 一定要看看 Spectre,它使这样的转换非常容易,几乎没有不便
【解决方案3】:

您也可以为此使用 clojure 拉链:

user> (require '[clojure.zip :as z])

user> (loop [curr (z/vector-zip start-pos)]
        (cond (z/end? curr) (z/root curr)
              (= :goose (z/node curr)) (recur (z/remove curr))
              :else (recur (z/next curr))))
;; => [[[:fox :corn :you] [:boat] []]]

此外,仅使用 clojure 的核心功能很容易做到这一点:

user> (defn remv [pred data]
        (if (vector? data)
          (mapv (partial remv pred) (remove pred data))
          data))
#'user/remv

user> (remv #{:goose} start-pos)
;; => [[[:fox :corn :you] [:boat] []]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-22
    • 2015-07-24
    • 1970-01-01
    • 2012-01-27
    相关资源
    最近更新 更多