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

时间:2014-05-31 20:17:34

标签: 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)))

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

2 个答案:

答案 0 :(得分: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))))))

答案 1 :(得分: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)))
相关问题