如何在Clojure中向数组地图添加元素?

时间:2017-11-07 16:50:46

标签: clojure

如何在Clojure中向数组地图添加元素?我尝试使用assoc,但它没有添加?我基本上想要为条目数组映射中的任何缺失项设置默认值0。

(defn create-entry [doc]
 (let [entry (assoc doc "id" (str (java.util.UUID/randomUUID)))]
  (if (empty? (get entry "foo")) (assoc entry "foo" 0))
  (if (empty? (get entry "bar")) (assoc entry "bar" 0))))

Carcigenicate评论后更新:

(defn entry [doc]
(as-> (assoc doc "id" (str (java.util.UUID/randomUUID))) e
      (if (empty? (get e "foo")) (assoc e "foo" 0) e)
      (if (empty? (get e "bar")) (assoc e "bar" 0) e)))

(defn create-entry [doc]
  (prn (entry doc)))

2 个答案:

答案 0 :(得分:2)

你需要开始思考更多功能。请注意您使用的所有结构是如何不可变的;他们自己永远不会改变。你的第二行最后一行是entry的副本,但你从不做任何事情;它被抛弃了。有几种方法可以处理这样的情况,你需要在几个步骤中转换结构:

  • 只需使用let

    (let [entry (assoc doc "id" (str (java.util.UUID/randomUUID)))
          def-foo (if (empty? (get entry "foo")) (assoc entry "foo" 0) entry)]
      (if (empty? (get def-foo "bar")) (assoc def-foo "bar" 0) def-foo)))
    

    请注意最后一行如何使用def-foo副本,而不是原始entry

  • 使用线程宏:

        ; Create a new binding, e, that will hold the result of the previous form
        (as-> (assoc doc "id" (str (java.util.UUID/randomUUID))) e
              (if (empty? (get e "foo")) (assoc e "foo" 0) e)
              (if (empty? (get e "bar")) (assoc e "bar" 0) e))
    

    e将被之前评估的形式所取代。

但请注意,如果您发现自己在同一个对象上使用getassoc,则可能需要考虑使用update,这极大地简化了所有内容,尤其是配对时使用->线程宏:

(-> (assoc doc "id" (str (java.util.UUID/randomUUID)))
    (update "foo" #(if (empty? %) 0 %))
    (update "bar" #(if (empty? %) 0 %)))

我必须对你的意图做出一些假设,因为你的代码有一个错误,直到我提交了我的答案之后我才注意到。在原始代码中,当条件为false时,if s不会评估任何内容。我假设你只是在他们错误时不想改变任何东西。

答案 1 :(得分:2)

补充Carcigenicate的回答,另一个建议是: 我在默认地图上使用mergeassoc

(merge {:default-1 123 :default-2 234} {:default-1 "foo"})
=> {:default-1 "foo", :default-2 234}

请注意,merge的参数顺序很重要,即最右边的地图优先于最左边的地图。您的默认地图值只会"幸存"如果他们没有被其他地图覆盖。

(def defaults {"foo" 0, "bar" 0})
(defn create-entry [doc]
  (assoc defaults "id" (str (java.util.UUID/randomUUID))))
(defn create-entry [doc]
  (merge defaults {"id" (str (java.util.UUID/randomUUID))}))

在此示例中使用assoc具有相同的效果,我更喜欢该版本。