Clojure 如何更新向量中符合特定条件的记录?

Clojure 如何更新向量中符合特定条件的记录?,clojure,Clojure,我正在尝试更新向量中符合某些条件的记录 (defrecord Item [id name description]) (def items (ref [ (->Item "1" "Cookies" "Good tasting!") (->Item "2" "Blueberries" "Healthy!") ]) ) 如何操作,例如“将项目名称设置为“foo”,其中id等于1” 我可能需要像这样的东西 (dosync (commute items ????

我正在尝试更新向量中符合某些条件的记录

(defrecord Item [id name description])

(def items
  (ref [
    (->Item "1" "Cookies" "Good tasting!")
    (->Item "2" "Blueberries" "Healthy!")

  ])
)
如何操作,例如“将项目名称设置为“foo”,其中id等于1”

我可能需要像这样的东西

(dosync (commute items ???? ))
我想不出这是什么

我发现,例如,功能

但是1。找不到包含记录的示例,2。不确定是否可以使用它来更新与我用于执行查询的字段不同的字段。在示例中,字段似乎是相同的

完整的用例:我有一个更新操作的webservice,其中我得到一个带有项目id的映射和必须更新的可选字段

我是新来Clojure的。我实现了删除功能,根据id,它可以工作:

(commute items #(remove (fn [x](= (:id x) id)) %))
还可以按id查找,这可能是更新方向的一个步骤:

(nth (filtered (filter #(= (:id %) id) @items)) 0)

但是不知道如何更新my vector中的记录…

您可以使用
assoc
创建一个记录副本,并替换一些键

(dosync
 (commute items
          #(mapv (fn [i]
                   (if (= (:id i) "1")
                     (assoc i :name "foo")
                     i))
                 %)))

您可以使用
assoc
制作记录的副本,并替换一些键

(dosync
 (commute items
          #(mapv (fn [i]
                   (if (= (:id i) "1")
                     (assoc i :name "foo")
                     i))
                 %)))

您可以使用
assoc
制作记录的副本,并替换一些键

(dosync
 (commute items
          #(mapv (fn [i]
                   (if (= (:id i) "1")
                     (assoc i :name "foo")
                     i))
                 %)))

您可以使用
assoc
制作记录的副本,并替换一些键

(dosync
 (commute items
          #(mapv (fn [i]
                   (if (= (:id i) "1")
                     (assoc i :name "foo")
                     i))
                 %)))


我建议你避免状态,复制而不是修改。大多数函数(如
assoc
和company)将返回新的数据结构(在
assoc
的情况下映射),而不是修改旧的数据结构。Clojure被要求考虑不变性而不是状态变化。当您以这种方式(惯用方式)理解它时,您将看到您的代码是如何变得更加清晰和简洁的。我自己也犯了这个错误,所以这是我的建议。我知道这一点。实际上,这些数据应该在数据库中。我只是暂时使用内存中的数据。仍然没关系,它是数据。不管怎样,你可能想调查一下。啊。您的意思是返回一个新的、修改过的数据结构,而不是更改元素。对这是有道理的。我意识到了函数式练习的好处:)现在只是玩一点,让语言变得流利。。。当然,我会记住这一点。@m0skit0无论如何,这些函数不是这样工作的吗?remove返回一个新的、更新的seq。然后必须使用dosync和Communion更新ref。同样在所选答案中,mapv返回更新的seq,然后更新ref。我遗漏了什么吗?我建议你避免进入状态,复制而不是修改。大多数函数(如
assoc
和company)将返回新的数据结构(在
assoc
的情况下映射),而不是修改旧的数据结构。Clojure被要求考虑不变性而不是状态变化。当您以这种方式(惯用方式)理解它时,您将看到您的代码是如何变得更加清晰和简洁的。我自己也犯了这个错误,所以这是我的建议。我知道这一点。实际上,这些数据应该在数据库中。我只是暂时使用内存中的数据。仍然没关系,它是数据。不管怎样,你可能想调查一下。啊。您的意思是返回一个新的、修改过的数据结构,而不是更改元素。对这是有道理的。我意识到了函数式练习的好处:)现在只是玩一点,让语言变得流利。。。当然,我会记住这一点。@m0skit0无论如何,这些函数不是这样工作的吗?remove返回一个新的、更新的seq。然后必须使用dosync和Communion更新ref。同样在所选答案中,mapv返回更新的seq,然后更新ref。我遗漏了什么吗?我建议你避免进入状态,复制而不是修改。大多数函数(如
assoc
和company)将返回新的数据结构(在
assoc
的情况下映射),而不是修改旧的数据结构。Clojure被要求考虑不变性而不是状态变化。当您以这种方式(惯用方式)理解它时,您将看到您的代码是如何变得更加清晰和简洁的。我自己也犯了这个错误,所以这是我的建议。我知道这一点。实际上,这些数据应该在数据库中。我只是暂时使用内存中的数据。仍然没关系,它是数据。不管怎样,你可能想调查一下。啊。您的意思是返回一个新的、修改过的数据结构,而不是更改元素。对这是有道理的。我意识到了函数式练习的好处:)现在只是玩一点,让语言变得流利。。。当然,我会记住这一点。@m0skit0无论如何,这些函数不是这样工作的吗?remove返回一个新的、更新的seq。然后必须使用dosync和Communion更新ref。同样在所选答案中,mapv返回更新的seq,然后更新ref。我遗漏了什么吗?我建议你避免进入状态,复制而不是修改。大多数函数(如
assoc
和company)将返回新的数据结构(在
assoc
的情况下映射),而不是修改旧的数据结构。Clojure被要求考虑不变性而不是状态变化。当您以这种方式(惯用方式)理解它时,您将看到您的代码是如何变得更加清晰和简洁的。我自己也犯了这个错误,所以这是我的建议。我知道这一点。实际上,这些数据应该在数据库中。我只是暂时使用内存中的数据。仍然没关系,它是数据。不管怎样,你可能想调查一下。啊。您的意思是返回一个新的、修改过的数据结构,而不是更改元素。对这是有道理的。我意识到了函数式练习的好处:)现在只是玩一点,让语言变得流利。。。当然,我会记住这一点。@m0skit0无论如何,这些函数不是这样工作的吗?remove返回一个新的、更新的seq。然后必须使用dosync和Communion更新ref。同样在所选答案中,mapv返回更新的seq,然后更新ref。我遗漏了什么吗?谢谢,它很有用!我只需将
(assoc I:name“foo”)
更改为
(merge I params)
即可使用我的参数映射更新项目。Tha