未能解除矢量项目的关联?陷入困境

Mik*_*din 2 clojure

我正在编写一个循环,它从向量中的字符串数据创建一个映射.在每次迭代中,我取向量中的最后一项,从中构造一个键和一个值,将它们与地图相关联,然后弹出刚刚从向量中记录到地图的项目.只要向量中仍有项目,此过程应不断重复,直到向量为空并且地图已满.

该函数如下:

(defn map-builder
  "Transforms the vector of waterfalls into a map of waterfalls."
  [input]
  (loop [waterfall-db {}
        vectorized-db input]
    (let [key-str (last vectorized-db)]
    key (->> key-str
            (re-seq #"[0-9]+")
             keyword)
    val (subs key-str (+ 2 (.indexOf key-str ":"))))
    (assoc waterfall-db key val)
    (pop vectorized-db)
  (if (> (count vectorized-db) 0)
    (recur waterfall-db vectorized-db) waterfall-db)))
Run Code Online (Sandbox Code Playgroud)

程序编译,但似乎无限循环.我做了一个测试,在一次迭代后使循环退出,并返回一个空映射(它应该有一个项目).很明显,我不正确地将项目与地图关联起来,这让我觉得我必须也不正确地将项目与向量分离.我无法看到我出错的地方 - 我是不是我的当地人不合适?

Jua*_*uel 7

在clojure中,数据结构不会就地更改:新数据结构值是从旧数据结构计算的.

  • 在你的代码中,你(pop vectorized-db)打算弹出最后一个元素.Clojure pop不会像这样工作,但会计算一个新元素,vectorized-db 但元素与最后一个元素相同.
  • 这同样适用于(assoc waterfal-db key val).

您需要做的是在recur调用中传递新值.代码(我没有测试过,因为我没有它应该做的例子)转换为:

(defn map-builder
  "Transforms the vector of waterfalls into a map of waterfalls."
  [input]
  (loop [waterfall-db {}
         vectorized-db input]
    (if (empty? vectorized-db)
      waterfall-db
      (let [key-str (last vectorized-db)
            key (->> key-str
                     (re-seq #"[0-9]+")
                     keyword)
            val (subs key-str (+ 2 (.indexOf key-str ":")))]
        (recur (assoc waterfall-db key val) (pop vectorized-db))))))
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 6

Juan Manuel发布的答案是正确的,但您可以考虑通过into哪种方式构建您的地图更直接:

(defn- make-kv [s]
    (let [key (->> s (re-seq #"[0-9]+") first keyword)
          val (-> s (.split ":") second string/trim)]
    [key val]))

(defn map-builder [v] 
    (into {} (map make-kv v)))
Run Code Online (Sandbox Code Playgroud)