在clojure中更新深层嵌套结构

时间:2015-02-06 14:57:39

标签: clojure

我有这样的结构:

[["/1417612109-first-migration.clj"  {:applied true :date-applied 1423233980}]
 ["/1417612450-second-migration.clj" {:applied false}]
 ["/1417615919-forth-migration.clj"  {:applied false}]]

我最终需要操纵它并返回它的新版本。为了找到我需要操纵的值,我使用filterfirst,它给了我我追求的矢量,E.G:

 ["/1417612450-second-migration.clj" {:applied false}]

我的问题是;如何更新该特定项目的地图而不必再次map整个地块?我能以某种方式使用上述作为参考吗?

2 个答案:

答案 0 :(得分:3)

如果你不需要为其他目的返回匹配向量,即你只是为了更新它而找到它,那么使用map而不是filter,首先使用一个函数检查每个条目以查看是否需要更新并根据需要返回已更改/未更改的条目。

(def test
  [["/1417612109-first-migration.clj"  {:applied true :date-applied 1423233980}]
   ["/1417612450-second-migration.clj" {:applied false}]
   ["/1417615919-forth-migration.clj"  {:applied false}]])

(map #(if (:applied (second %))
        % ; if applied is already true then use it unchanged
        (assoc-in % [1 :applied] true)) ; if applied is false update it
     test)

; (["/1417612109-first-migration.clj" {:applied true, :date-applied 1423233980}]
;  ["/1417612450-second-migration.clj" {:applied true}]
;  ["/1417615919-forth-migration.clj" {:applied true}])

如果您不需要外部集合作为矢量,那么您可以将其设为地图,然后使用例如“/1417612450-second-migration.clj”作为关联或更新的关键。

(def test-map
  {"/1417612109-first-migration.clj"  {:applied true :date-applied 1423233980}
   "/1417612450-second-migration.clj" {:applied false}
   "/1417615919-forth-migration.clj"  {:applied false}})

(def result ["/1417612450-second-migration.clj" {:applied false}])

(assoc-in test-map [(first result) :applied] true)

;{"/1417612109-first-migration.clj" {:applied true, :date-applied 1423233980},
; "/1417612450-second-migration.clj" {:applied true}, 
;"/1417615919-forth-migration.clj" {:applied false}}

答案 1 :(得分:0)

您可以使用更新功能https://clojuredocs.org/clojure.core/update-in

(update-in my-vector [0 1 :applied] f)

其中f是一个接受旧值并返回新值的函数。此示例将从第一个向量更新地图中的应用值。它也适用于深层结构。有关更多信息,请参阅文档。