如何在Clojure中向数组映射添加元素?

如何在Clojure中向数组映射添加元素?,clojure,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

如何在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)))

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

  • 只需使用

    (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
    副本,而不是原始
    条目

  • 使用线程宏:

        ; 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))
    
    (-> (assoc doc "id" (str (java.util.UUID/randomUUID)))
        (update "foo" #(if (empty? %) 0 %))
        (update "bar" #(if (empty? %) 0 %)))
    
    e
    将替换为前面的任何形式

注意,如果你发现自己在同一个对象上使用了<代码>获取<代码> >代码> AsSOC/<代码>,你可能需要考虑使用<代码> Update < /Cord>,这大大简化了一切,特别是当与<代码> -> /Cord>线程宏:

配对时
    ; 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))
(-> (assoc doc "id" (str (java.util.UUID/randomUUID)))
    (update "foo" #(if (empty? %) 0 %))
    (update "bar" #(if (empty? %) 0 %)))


我不得不对您的意图做一些假设,因为您的代码有一个错误,我在提交答案之前没有注意到这个错误。在原始代码中,当条件为false时,
if
s不会计算为任何值。我假设你只是不想改变任何错误的东西

你需要开始思考更实用的问题。请注意,您使用的所有结构都是不可变的;他们自己永远不会改变。您的最后一行复制了
条目
,但您从未对其进行任何操作;它刚刚被扔掉了。有几种处理这种情况的方法,您需要通过几个步骤转换结构:

  • 只需使用

    (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
    副本,而不是原始
    条目

  • 使用线程宏:

        ; 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))
    
    (-> (assoc doc "id" (str (java.util.UUID/randomUUID)))
        (update "foo" #(if (empty? %) 0 %))
        (update "bar" #(if (empty? %) 0 %)))
    
    e
    将替换为前面的任何形式

注意,如果你发现自己在同一个对象上使用了<代码>获取<代码> >代码> AsSOC/<代码>,你可能需要考虑使用<代码> Update < /Cord>,这大大简化了一切,特别是当与<代码> -> /Cord>线程宏:

配对时
    ; 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))
(-> (assoc doc "id" (str (java.util.UUID/randomUUID)))
    (update "foo" #(if (empty? %) 0 %))
    (update "bar" #(if (empty? %) 0 %)))


我不得不对您的意图做一些假设,因为您的代码有一个错误,我在提交答案之前没有注意到这个错误。在原始代码中,当条件为false时,
if
s不会计算为任何值。我假设你只是不想改变任何错误的东西

为了补充Carcigenicate的回答,另一个建议是: 我会在默认地图上使用
merge
assoc

(merge {:default-1 123 :default-2 234} {:default-1 "foo"})
=> {:default-1 "foo", :default-2 234}
请注意,
merge
的参数顺序很重要,即最右边的映射优先于最左边的映射。默认贴图值只有在未被其他贴图覆盖时才会“保留”


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

为了补充Carcigenicate的答案,另一个建议是: 我会在默认地图上使用
merge
assoc

(merge {:default-1 123 :default-2 234} {:default-1 "foo"})
=> {:default-1 "foo", :default-2 234}
请注意,
merge
的参数顺序很重要,即最右边的映射优先于最左边的映射。默认贴图值只有在未被其他贴图覆盖时才会“保留”


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

感谢您提供的详细答案。你可能知道我对Clojure很陌生。我尝试使用threading宏跟踪您的答案,并用代码更改更新了帖子。但是,我不确定我是否正确解释了您的答案,因为我仍然无法打印foo或bar的默认值。@Freid001您需要调用
entry
,方法是将其括在括号中:
(prn(entry doc))
。请记住,符号必须是要调用的表单中的第一个元素。你所有的代码都在打印关于函数本身的信息,因为你从未调用过它。谢谢,我可以看到默认值。我只是用
prn
来记录控制台的响应。正如我之前所说的,我对Clojure非常陌生。您是否可以推荐一些文档来帮助我更好地理解线程宏概念?@Freid001 Np。而且Clojure的文档非常优秀。如果我是你的话,我会开始回复,然后和他们混在一起。不过还是从
->
开始吧,因为这是最简单的。阅读文档,然后播放。你会明白的。谢谢你详细的回答。你可能知道我对Clojure很陌生。我尝试使用threading宏跟踪您的答案,并用代码更改更新了帖子。但是,我不确定我是否正确解释了您的答案,因为我仍然无法打印foo或bar的默认值。@Freid001您需要调用
entry
,方法是将其括在括号中:
(prn(entry doc))
。请记住,符号必须是要调用的表单中的第一个元素。你所有的代码都在打印关于函数本身的信息,因为你从未调用过它。谢谢,我可以看到默认值。我只是用
prn
来记录控制台的响应。正如我之前所说的,我对Clojure非常陌生。您是否可以推荐一些文档来帮助我更好地理解线程宏概念?@Freid001 Np。而且Clojure的文档非常优秀。如果我是你的话,我会开始回复,然后和他们混在一起。不过还是从
->
开始吧,因为这是最简单的。阅读文档,然后播放。你会明白的。