我正在编写一个循环,它从向量中的字符串数据创建一个映射.在每次迭代中,我取向量中的最后一项,从中构造一个键和一个值,将它们与地图相关联,然后弹出刚刚从向量中记录到地图的项目.只要向量中仍有项目,此过程应不断重复,直到向量为空并且地图已满.
该函数如下:
(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)
程序编译,但似乎无限循环.我做了一个测试,在一次迭代后使循环退出,并返回一个空映射(它应该有一个项目).很明显,我不正确地将项目与地图关联起来,这让我觉得我必须也不正确地将项目与向量分离.我无法看到我出错的地方 - 我是不是我的当地人不合适?
在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)
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)