如何在Clojure中向数组映射添加元素? [英] How do I add an element to an array-map in Clojure?

查看:101
本文介绍了如何在Clojure中向数组映射添加元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在Clojure中将元素添加到数组映射中?我尝试使用assoc,但没有添加?我本质上是想为条目array-map中的所有缺失项设置默认值0。

How can I add an element to an array-map in Clojure? I tried using assoc but it doesn't get added? I essentially want to set a default value of 0 for any missing items in the entry array-map.

(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发表评论后更新:

Update after comments from 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)))


推荐答案

您需要开始考虑更多功能。请注意,您正在使用的所有结构都是不可变的;他们自己永远不会改变。最后一行复制 entry 的副本,但您永远不会对其进行任何操作。它只是被扔掉了。有几种处理这种情况的方法,您需要通过几个步骤来转换结构:

You need to starting thinking more functional. Note how all the structures you're using are immutable; they themselves can never change. Your second last line makes a copy of entry, but you never do anything with it; it's just thrown out. There are a few ways of dealing with situations like this where you need to transform a structure over a couple steps:


  • 仅使用 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

Note how the last line uses the def-foo copy, instead of the original 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 替换为以前的格式

不过请注意,如果您发现自己使用 get assoc 在同一个对象上,您可能要考虑使用 update 来代替,这大大简化了所有操作,尤其是与-> 线程宏配对时:

Note though, that if you ever find yourself using get and assoc on the same object, you might want to consider using update instead, which greatly simplifies everything, especially when paired with the -> threading macro:

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






我必须对您的意图做一些假设,因为您的代码有错误直到我提交答案后我才注意到。在原始代码中,如果条件为假,则您的 if 不会计算任何值。我假设您只是不想更改任何错误的内容。


I had to make some assumptions about what your intent was, because your code has an error that I didn't notice until after I had already submitted my answer. In your original code, your ifs don't evaluate to anything when the condition is false. I'm assuming you just don't want to change anything when they're false.

这篇关于如何在Clojure中向数组映射添加元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆